1// Copyright 2018 The Fuchsia Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <ddk/debug.h> 6#include <ddk/device.h> 7#include <ddk/io-buffer.h> 8#include <ddk/metadata.h> 9#include <ddk/metadata/nand.h> 10#include <ddk/protocol/gpio.h> 11#include <ddk/protocol/platform-bus.h> 12#include <ddk/protocol/platform-defs.h> 13#include <hw/reg.h> 14#include <soc/aml-a113/a113-hw.h> 15#include <unistd.h> 16#include <zircon/hw/gpt.h> 17 18#include "gauss.h" 19#include "gauss-hw.h" 20 21static const pbus_mmio_t raw_nand_mmios[] = { 22 { /* nandreg : Registers for NAND controller */ 23 .base = GAUSS_RAW_NAND_REG, 24 .length = 0x2000, 25 }, 26 { /* clockreg : Clock Register for NAND controller */ 27 /* 28 * From the Linux devicetree. This is the base SD_EMMC_CLOCK 29 * register (for port C) 30 */ 31 .base = GAUSS_RAW_NAND_CLKREG, 32 .length = 0x4, /* Just 4 bytes */ 33 }, 34}; 35 36static const pbus_irq_t raw_nand_irqs[] = { 37 { 38 .irq = GAUSS_RAW_NAND_IRQ, 39 }, 40}; 41 42static const pbus_bti_t raw_nand_btis[] = { 43 { 44 .iommu_index = 0, 45 .bti_id = BTI_AML_RAW_NAND, 46 }, 47}; 48 49static const nand_config_t config = { 50 .bad_block_config = { 51 .type = kAmlogicUboot, 52 .aml = { 53 .table_start_block = 20, 54 .table_end_block = 23, 55 }, 56 }, 57 .extra_partition_config_count = 1, 58 .extra_partition_config = { 59 { 60 .type_guid = GUID_BOOTLOADER_VALUE, 61 .copy_count = 4, 62 }, 63 }, 64}; 65 66static const pbus_metadata_t raw_nand_metadata[] = { 67 { 68 .type = DEVICE_METADATA_PRIVATE, 69 .data = &config, 70 .len = sizeof(config), 71 }, 72}; 73 74static const pbus_boot_metadata_t raw_nand_boot_metadata[] = { 75 { 76 .zbi_type = DEVICE_METADATA_PARTITION_MAP, 77 .zbi_extra = 0, 78 }, 79}; 80 81static const pbus_dev_t raw_nand_dev = { 82 .name = "aml_raw_nand", 83 .vid = PDEV_VID_AMLOGIC, 84 .pid = PDEV_PID_GENERIC, 85 .did = PDEV_DID_AMLOGIC_RAW_NAND, 86 .mmios = raw_nand_mmios, 87 .mmio_count = countof(raw_nand_mmios), 88 .irqs = raw_nand_irqs, 89 .irq_count = countof(raw_nand_irqs), 90 .btis = raw_nand_btis, 91 .bti_count = countof(raw_nand_btis), 92 .metadata = raw_nand_metadata, 93 .metadata_count = countof(raw_nand_metadata), 94 .boot_metadata = raw_nand_boot_metadata, 95 .boot_metadata_count = countof(raw_nand_boot_metadata), 96}; 97 98zx_status_t gauss_raw_nand_init(gauss_bus_t* bus) { 99 zx_status_t status; 100 101 // set alternate functions to enable raw_nand 102 status = gpio_impl_set_alt_function(&bus->gpio, A113_GPIOBOOT(8), 2); 103 if (status != ZX_OK) 104 return status; 105 status = gpio_impl_set_alt_function(&bus->gpio, A113_GPIOBOOT(9), 2); 106 if (status != ZX_OK) 107 return status; 108 status = gpio_impl_set_alt_function(&bus->gpio, A113_GPIOBOOT(10), 2); 109 if (status != ZX_OK) 110 return status; 111 status = gpio_impl_set_alt_function(&bus->gpio, A113_GPIOBOOT(11), 2); 112 if (status != ZX_OK) 113 return status; 114 status = gpio_impl_set_alt_function(&bus->gpio, A113_GPIOBOOT(12), 2); 115 if (status != ZX_OK) 116 return status; 117 status = gpio_impl_set_alt_function(&bus->gpio, A113_GPIOBOOT(13), 2); 118 if (status != ZX_OK) 119 return status; 120 121 status = pbus_device_add(&bus->pbus, &raw_nand_dev); 122 if (status != ZX_OK) { 123 zxlogf(ERROR, "gauss_raw_nand_init: pbus_device_add raw_nand failed: %d\n", 124 status); 125 return status; 126 } 127 128 return ZX_OK; 129} 130 131