1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * NAND Flash Controller Device Driver |
4 | * Copyright © 2009-2010, Intel Corporation and its suppliers. |
5 | */ |
6 | |
7 | #include <linux/errno.h> |
8 | #include <linux/io.h> |
9 | #include <linux/kernel.h> |
10 | #include <linux/module.h> |
11 | #include <linux/pci.h> |
12 | |
13 | #include "denali.h" |
14 | |
15 | #define DENALI_NAND_NAME "denali-nand-pci" |
16 | |
17 | #define INTEL_CE4100 1 |
18 | #define INTEL_MRST 2 |
19 | |
20 | /* List of platforms this NAND controller has be integrated into */ |
21 | static const struct pci_device_id denali_pci_ids[] = { |
22 | { PCI_VDEVICE(INTEL, 0x0701), INTEL_CE4100 }, |
23 | { PCI_VDEVICE(INTEL, 0x0809), INTEL_MRST }, |
24 | { /* end: all zeroes */ } |
25 | }; |
26 | MODULE_DEVICE_TABLE(pci, denali_pci_ids); |
27 | |
28 | NAND_ECC_CAPS_SINGLE(denali_pci_ecc_caps, denali_calc_ecc_bytes, 512, 8, 15); |
29 | |
30 | static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) |
31 | { |
32 | resource_size_t csr_base, mem_base; |
33 | unsigned long csr_len, mem_len; |
34 | struct denali_controller *denali; |
35 | struct denali_chip *dchip; |
36 | int nsels, ret, i; |
37 | |
38 | denali = devm_kzalloc(dev: &dev->dev, size: sizeof(*denali), GFP_KERNEL); |
39 | if (!denali) |
40 | return -ENOMEM; |
41 | |
42 | ret = pcim_enable_device(pdev: dev); |
43 | if (ret) { |
44 | dev_err(&dev->dev, "Spectra: pci_enable_device failed.\n" ); |
45 | return ret; |
46 | } |
47 | |
48 | if (id->driver_data == INTEL_CE4100) { |
49 | mem_base = pci_resource_start(dev, 0); |
50 | mem_len = pci_resource_len(dev, 1); |
51 | csr_base = pci_resource_start(dev, 1); |
52 | csr_len = pci_resource_len(dev, 1); |
53 | } else { |
54 | csr_base = pci_resource_start(dev, 0); |
55 | csr_len = pci_resource_len(dev, 0); |
56 | mem_base = pci_resource_start(dev, 1); |
57 | mem_len = pci_resource_len(dev, 1); |
58 | if (!mem_len) { |
59 | mem_base = csr_base + csr_len; |
60 | mem_len = csr_len; |
61 | } |
62 | } |
63 | |
64 | pci_set_master(dev); |
65 | denali->dev = &dev->dev; |
66 | denali->irq = dev->irq; |
67 | denali->ecc_caps = &denali_pci_ecc_caps; |
68 | denali->clk_rate = 50000000; /* 50 MHz */ |
69 | denali->clk_x_rate = 200000000; /* 200 MHz */ |
70 | |
71 | ret = pci_request_regions(dev, DENALI_NAND_NAME); |
72 | if (ret) { |
73 | dev_err(&dev->dev, "Spectra: Unable to request memory regions\n" ); |
74 | return ret; |
75 | } |
76 | |
77 | denali->reg = devm_ioremap(dev: denali->dev, offset: csr_base, size: csr_len); |
78 | if (!denali->reg) { |
79 | dev_err(&dev->dev, "Spectra: Unable to remap memory region\n" ); |
80 | return -ENOMEM; |
81 | } |
82 | |
83 | denali->host = devm_ioremap(dev: denali->dev, offset: mem_base, size: mem_len); |
84 | if (!denali->host) { |
85 | dev_err(&dev->dev, "Spectra: ioremap failed!" ); |
86 | return -ENOMEM; |
87 | } |
88 | |
89 | ret = denali_init(denali); |
90 | if (ret) |
91 | return ret; |
92 | |
93 | nsels = denali->nbanks; |
94 | |
95 | dchip = devm_kzalloc(dev: denali->dev, struct_size(dchip, sels, nsels), |
96 | GFP_KERNEL); |
97 | if (!dchip) { |
98 | ret = -ENOMEM; |
99 | goto out_remove_denali; |
100 | } |
101 | |
102 | dchip->chip.base.ecc.user_conf.flags |= NAND_ECC_MAXIMIZE_STRENGTH; |
103 | |
104 | dchip->nsels = nsels; |
105 | |
106 | for (i = 0; i < nsels; i++) |
107 | dchip->sels[i].bank = i; |
108 | |
109 | ret = denali_chip_init(denali, dchip); |
110 | if (ret) |
111 | goto out_remove_denali; |
112 | |
113 | pci_set_drvdata(pdev: dev, data: denali); |
114 | |
115 | return 0; |
116 | |
117 | out_remove_denali: |
118 | denali_remove(denali); |
119 | return ret; |
120 | } |
121 | |
122 | static void denali_pci_remove(struct pci_dev *dev) |
123 | { |
124 | struct denali_controller *denali = pci_get_drvdata(pdev: dev); |
125 | |
126 | denali_remove(denali); |
127 | } |
128 | |
129 | static struct pci_driver denali_pci_driver = { |
130 | .name = DENALI_NAND_NAME, |
131 | .id_table = denali_pci_ids, |
132 | .probe = denali_pci_probe, |
133 | .remove = denali_pci_remove, |
134 | }; |
135 | module_pci_driver(denali_pci_driver); |
136 | |
137 | MODULE_DESCRIPTION("PCI driver for Denali NAND controller" ); |
138 | MODULE_AUTHOR("Intel Corporation and its suppliers" ); |
139 | MODULE_LICENSE("GPL v2" ); |
140 | |