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-s905d2/s905d2-hw.h> 15#include <soc/aml-s905d2/s905d2-gpio.h> 16#include <unistd.h> 17#include <zircon/hw/gpt.h> 18 19#include "astro.h" 20 21static const pbus_mmio_t raw_nand_mmios[] = { 22 { /* nandreg : Registers for NAND controller */ 23 .base = S905D2_RAW_NAND_REG_BASE, 24 .length = 0x2000, 25 }, 26 { /* clockreg : Clock Register for NAND controller */ 27 .base = S905D2_RAW_NAND_CLOCK_BASE, 28 .length = 0x4, /* Just 4 bytes */ 29 }, 30}; 31 32static const pbus_irq_t raw_nand_irqs[] = { 33 { 34 .irq = S905D2_RAW_NAND_IRQ, 35 }, 36}; 37 38static const pbus_bti_t raw_nand_btis[] = { 39 { 40 .iommu_index = 0, 41 .bti_id = BTI_AML_RAW_NAND, 42 }, 43}; 44 45static const nand_config_t config = { 46 .bad_block_config = { 47 .type = kAmlogicUboot, 48 .aml = { 49 .table_start_block = 20, 50 .table_end_block = 23, 51 }, 52 }, 53 .extra_partition_config_count = 1, 54 .extra_partition_config = { 55 { 56 .type_guid = GUID_BOOTLOADER_VALUE, 57 .copy_count = 4, 58 }, 59 }, 60}; 61 62static const pbus_metadata_t raw_nand_metadata[] = { 63 { 64 .type = DEVICE_METADATA_PRIVATE, 65 .data = &config, 66 .len = sizeof(config), 67 }, 68}; 69 70static const pbus_boot_metadata_t raw_nand_boot_metadata[] = { 71 { 72 .zbi_type = DEVICE_METADATA_PARTITION_MAP, 73 .zbi_extra = 0, 74 }, 75}; 76 77static const pbus_dev_t raw_nand_dev = { 78 .name = "aml_raw_nand", 79 .vid = PDEV_VID_AMLOGIC, 80 .pid = PDEV_PID_GENERIC, 81 .did = PDEV_DID_AMLOGIC_RAW_NAND, 82 .mmios = raw_nand_mmios, 83 .mmio_count = countof(raw_nand_mmios), 84 .irqs = raw_nand_irqs, 85 .irq_count = countof(raw_nand_irqs), 86 .btis = raw_nand_btis, 87 .bti_count = countof(raw_nand_btis), 88 .metadata = raw_nand_metadata, 89 .metadata_count = countof(raw_nand_metadata), 90 .boot_metadata = raw_nand_boot_metadata, 91 .boot_metadata_count = countof(raw_nand_boot_metadata), 92}; 93 94zx_status_t aml_raw_nand_init(aml_bus_t* bus) { 95 zx_status_t status; 96 97 // Set alternate functions to enable raw_nand. 98 status = gpio_impl_set_alt_function(&bus->gpio, S905D2_GPIOBOOT(8), 2); 99 if (status != ZX_OK) 100 return status; 101 status = gpio_impl_set_alt_function(&bus->gpio, S905D2_GPIOBOOT(9), 2); 102 if (status != ZX_OK) 103 return status; 104 status = gpio_impl_set_alt_function(&bus->gpio, S905D2_GPIOBOOT(10), 2); 105 if (status != ZX_OK) 106 return status; 107 status = gpio_impl_set_alt_function(&bus->gpio, S905D2_GPIOBOOT(11), 2); 108 if (status != ZX_OK) 109 return status; 110 status = gpio_impl_set_alt_function(&bus->gpio, S905D2_GPIOBOOT(12), 2); 111 if (status != ZX_OK) 112 return status; 113 status = gpio_impl_set_alt_function(&bus->gpio, S905D2_GPIOBOOT(14), 2); 114 if (status != ZX_OK) 115 return status; 116 status = gpio_impl_set_alt_function(&bus->gpio, S905D2_GPIOBOOT(15), 2); 117 if (status != ZX_OK) 118 return status; 119 120 status = pbus_device_add(&bus->pbus, &raw_nand_dev); 121 if (status != ZX_OK) { 122 zxlogf(ERROR, "%s: pbus_device_add failed: %d\n", 123 __func__, status); 124 return status; 125 } 126 127 return ZX_OK; 128} 129 130