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