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/platform-defs.h>
11 #include <ddk/protocol/gpio.h>
12 #include <ddk/protocol/platform/bus.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 
21 static 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 
36 static const pbus_irq_t raw_nand_irqs[] = {
37     {
38         .irq = GAUSS_RAW_NAND_IRQ,
39     },
40 };
41 
42 static const pbus_bti_t raw_nand_btis[] = {
43     {
44         .iommu_index = 0,
45         .bti_id = BTI_AML_RAW_NAND,
46     },
47 };
48 
49 static 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 
66 static const pbus_metadata_t raw_nand_metadata[] = {
67     {
68         .type = DEVICE_METADATA_PRIVATE,
69         .data_buffer = &config,
70         .data_size = sizeof(config),
71     },
72 };
73 
74 static const pbus_boot_metadata_t raw_nand_boot_metadata[] = {
75     {
76         .zbi_type = DEVICE_METADATA_PARTITION_MAP,
77         .zbi_extra = 0,
78     },
79 };
80 
81 static 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     .mmio_list = raw_nand_mmios,
87     .mmio_count = countof(raw_nand_mmios),
88     .irq_list = raw_nand_irqs,
89     .irq_count = countof(raw_nand_irqs),
90     .bti_list = raw_nand_btis,
91     .bti_count = countof(raw_nand_btis),
92     .metadata_list = raw_nand_metadata,
93     .metadata_count = countof(raw_nand_metadata),
94     .boot_metadata_list = raw_nand_boot_metadata,
95     .boot_metadata_count = countof(raw_nand_boot_metadata),
96 };
97 
gauss_raw_nand_init(gauss_bus_t * bus)98 zx_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