1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright (C) 2015 Hisilicon Limited, All Rights Reserved.
4*4882a593Smuzhiyun * Author: Jun Ma <majun258@huawei.com>
5*4882a593Smuzhiyun * Author: Yun Wu <wuyun.wu@huawei.com>
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #include <linux/acpi.h>
9*4882a593Smuzhiyun #include <linux/interrupt.h>
10*4882a593Smuzhiyun #include <linux/irqchip.h>
11*4882a593Smuzhiyun #include <linux/module.h>
12*4882a593Smuzhiyun #include <linux/msi.h>
13*4882a593Smuzhiyun #include <linux/of_address.h>
14*4882a593Smuzhiyun #include <linux/of_irq.h>
15*4882a593Smuzhiyun #include <linux/of_platform.h>
16*4882a593Smuzhiyun #include <linux/platform_device.h>
17*4882a593Smuzhiyun #include <linux/slab.h>
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun /* Interrupt numbers per mbigen node supported */
20*4882a593Smuzhiyun #define IRQS_PER_MBIGEN_NODE 128
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun /* 64 irqs (Pin0-pin63) are reserved for each mbigen chip */
23*4882a593Smuzhiyun #define RESERVED_IRQ_PER_MBIGEN_CHIP 64
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun /* The maximum IRQ pin number of mbigen chip(start from 0) */
26*4882a593Smuzhiyun #define MAXIMUM_IRQ_PIN_NUM 1407
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun /**
29*4882a593Smuzhiyun * In mbigen vector register
30*4882a593Smuzhiyun * bit[21:12]: event id value
31*4882a593Smuzhiyun * bit[11:0]: device id
32*4882a593Smuzhiyun */
33*4882a593Smuzhiyun #define IRQ_EVENT_ID_SHIFT 12
34*4882a593Smuzhiyun #define IRQ_EVENT_ID_MASK 0x3ff
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun /* register range of each mbigen node */
37*4882a593Smuzhiyun #define MBIGEN_NODE_OFFSET 0x1000
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun /* offset of vector register in mbigen node */
40*4882a593Smuzhiyun #define REG_MBIGEN_VEC_OFFSET 0x200
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun /**
43*4882a593Smuzhiyun * offset of clear register in mbigen node
44*4882a593Smuzhiyun * This register is used to clear the status
45*4882a593Smuzhiyun * of interrupt
46*4882a593Smuzhiyun */
47*4882a593Smuzhiyun #define REG_MBIGEN_CLEAR_OFFSET 0xa000
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun /**
50*4882a593Smuzhiyun * offset of interrupt type register
51*4882a593Smuzhiyun * This register is used to configure interrupt
52*4882a593Smuzhiyun * trigger type
53*4882a593Smuzhiyun */
54*4882a593Smuzhiyun #define REG_MBIGEN_TYPE_OFFSET 0x0
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun /**
57*4882a593Smuzhiyun * struct mbigen_device - holds the information of mbigen device.
58*4882a593Smuzhiyun *
59*4882a593Smuzhiyun * @pdev: pointer to the platform device structure of mbigen chip.
60*4882a593Smuzhiyun * @base: mapped address of this mbigen chip.
61*4882a593Smuzhiyun */
62*4882a593Smuzhiyun struct mbigen_device {
63*4882a593Smuzhiyun struct platform_device *pdev;
64*4882a593Smuzhiyun void __iomem *base;
65*4882a593Smuzhiyun };
66*4882a593Smuzhiyun
get_mbigen_vec_reg(irq_hw_number_t hwirq)67*4882a593Smuzhiyun static inline unsigned int get_mbigen_vec_reg(irq_hw_number_t hwirq)
68*4882a593Smuzhiyun {
69*4882a593Smuzhiyun unsigned int nid, pin;
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun hwirq -= RESERVED_IRQ_PER_MBIGEN_CHIP;
72*4882a593Smuzhiyun nid = hwirq / IRQS_PER_MBIGEN_NODE + 1;
73*4882a593Smuzhiyun pin = hwirq % IRQS_PER_MBIGEN_NODE;
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun return pin * 4 + nid * MBIGEN_NODE_OFFSET
76*4882a593Smuzhiyun + REG_MBIGEN_VEC_OFFSET;
77*4882a593Smuzhiyun }
78*4882a593Smuzhiyun
get_mbigen_type_reg(irq_hw_number_t hwirq,u32 * mask,u32 * addr)79*4882a593Smuzhiyun static inline void get_mbigen_type_reg(irq_hw_number_t hwirq,
80*4882a593Smuzhiyun u32 *mask, u32 *addr)
81*4882a593Smuzhiyun {
82*4882a593Smuzhiyun unsigned int nid, irq_ofst, ofst;
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun hwirq -= RESERVED_IRQ_PER_MBIGEN_CHIP;
85*4882a593Smuzhiyun nid = hwirq / IRQS_PER_MBIGEN_NODE + 1;
86*4882a593Smuzhiyun irq_ofst = hwirq % IRQS_PER_MBIGEN_NODE;
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun *mask = 1 << (irq_ofst % 32);
89*4882a593Smuzhiyun ofst = irq_ofst / 32 * 4;
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun *addr = ofst + nid * MBIGEN_NODE_OFFSET
92*4882a593Smuzhiyun + REG_MBIGEN_TYPE_OFFSET;
93*4882a593Smuzhiyun }
94*4882a593Smuzhiyun
get_mbigen_clear_reg(irq_hw_number_t hwirq,u32 * mask,u32 * addr)95*4882a593Smuzhiyun static inline void get_mbigen_clear_reg(irq_hw_number_t hwirq,
96*4882a593Smuzhiyun u32 *mask, u32 *addr)
97*4882a593Smuzhiyun {
98*4882a593Smuzhiyun unsigned int ofst = (hwirq / 32) * 4;
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun *mask = 1 << (hwirq % 32);
101*4882a593Smuzhiyun *addr = ofst + REG_MBIGEN_CLEAR_OFFSET;
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun
mbigen_eoi_irq(struct irq_data * data)104*4882a593Smuzhiyun static void mbigen_eoi_irq(struct irq_data *data)
105*4882a593Smuzhiyun {
106*4882a593Smuzhiyun void __iomem *base = data->chip_data;
107*4882a593Smuzhiyun u32 mask, addr;
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun get_mbigen_clear_reg(data->hwirq, &mask, &addr);
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun writel_relaxed(mask, base + addr);
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun irq_chip_eoi_parent(data);
114*4882a593Smuzhiyun }
115*4882a593Smuzhiyun
mbigen_set_type(struct irq_data * data,unsigned int type)116*4882a593Smuzhiyun static int mbigen_set_type(struct irq_data *data, unsigned int type)
117*4882a593Smuzhiyun {
118*4882a593Smuzhiyun void __iomem *base = data->chip_data;
119*4882a593Smuzhiyun u32 mask, addr, val;
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun if (type != IRQ_TYPE_LEVEL_HIGH && type != IRQ_TYPE_EDGE_RISING)
122*4882a593Smuzhiyun return -EINVAL;
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun get_mbigen_type_reg(data->hwirq, &mask, &addr);
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun val = readl_relaxed(base + addr);
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun if (type == IRQ_TYPE_LEVEL_HIGH)
129*4882a593Smuzhiyun val |= mask;
130*4882a593Smuzhiyun else
131*4882a593Smuzhiyun val &= ~mask;
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun writel_relaxed(val, base + addr);
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun return 0;
136*4882a593Smuzhiyun }
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun static struct irq_chip mbigen_irq_chip = {
139*4882a593Smuzhiyun .name = "mbigen-v2",
140*4882a593Smuzhiyun .irq_mask = irq_chip_mask_parent,
141*4882a593Smuzhiyun .irq_unmask = irq_chip_unmask_parent,
142*4882a593Smuzhiyun .irq_eoi = mbigen_eoi_irq,
143*4882a593Smuzhiyun .irq_set_type = mbigen_set_type,
144*4882a593Smuzhiyun .irq_set_affinity = irq_chip_set_affinity_parent,
145*4882a593Smuzhiyun };
146*4882a593Smuzhiyun
mbigen_write_msg(struct msi_desc * desc,struct msi_msg * msg)147*4882a593Smuzhiyun static void mbigen_write_msg(struct msi_desc *desc, struct msi_msg *msg)
148*4882a593Smuzhiyun {
149*4882a593Smuzhiyun struct irq_data *d = irq_get_irq_data(desc->irq);
150*4882a593Smuzhiyun void __iomem *base = d->chip_data;
151*4882a593Smuzhiyun u32 val;
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun if (!msg->address_lo && !msg->address_hi)
154*4882a593Smuzhiyun return;
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun base += get_mbigen_vec_reg(d->hwirq);
157*4882a593Smuzhiyun val = readl_relaxed(base);
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun val &= ~(IRQ_EVENT_ID_MASK << IRQ_EVENT_ID_SHIFT);
160*4882a593Smuzhiyun val |= (msg->data << IRQ_EVENT_ID_SHIFT);
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun /* The address of doorbell is encoded in mbigen register by default
163*4882a593Smuzhiyun * So,we don't need to program the doorbell address at here
164*4882a593Smuzhiyun */
165*4882a593Smuzhiyun writel_relaxed(val, base);
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun
mbigen_domain_translate(struct irq_domain * d,struct irq_fwspec * fwspec,unsigned long * hwirq,unsigned int * type)168*4882a593Smuzhiyun static int mbigen_domain_translate(struct irq_domain *d,
169*4882a593Smuzhiyun struct irq_fwspec *fwspec,
170*4882a593Smuzhiyun unsigned long *hwirq,
171*4882a593Smuzhiyun unsigned int *type)
172*4882a593Smuzhiyun {
173*4882a593Smuzhiyun if (is_of_node(fwspec->fwnode) || is_acpi_device_node(fwspec->fwnode)) {
174*4882a593Smuzhiyun if (fwspec->param_count != 2)
175*4882a593Smuzhiyun return -EINVAL;
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun if ((fwspec->param[0] > MAXIMUM_IRQ_PIN_NUM) ||
178*4882a593Smuzhiyun (fwspec->param[0] < RESERVED_IRQ_PER_MBIGEN_CHIP))
179*4882a593Smuzhiyun return -EINVAL;
180*4882a593Smuzhiyun else
181*4882a593Smuzhiyun *hwirq = fwspec->param[0];
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun /* If there is no valid irq type, just use the default type */
184*4882a593Smuzhiyun if ((fwspec->param[1] == IRQ_TYPE_EDGE_RISING) ||
185*4882a593Smuzhiyun (fwspec->param[1] == IRQ_TYPE_LEVEL_HIGH))
186*4882a593Smuzhiyun *type = fwspec->param[1];
187*4882a593Smuzhiyun else
188*4882a593Smuzhiyun return -EINVAL;
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun return 0;
191*4882a593Smuzhiyun }
192*4882a593Smuzhiyun return -EINVAL;
193*4882a593Smuzhiyun }
194*4882a593Smuzhiyun
mbigen_irq_domain_alloc(struct irq_domain * domain,unsigned int virq,unsigned int nr_irqs,void * args)195*4882a593Smuzhiyun static int mbigen_irq_domain_alloc(struct irq_domain *domain,
196*4882a593Smuzhiyun unsigned int virq,
197*4882a593Smuzhiyun unsigned int nr_irqs,
198*4882a593Smuzhiyun void *args)
199*4882a593Smuzhiyun {
200*4882a593Smuzhiyun struct irq_fwspec *fwspec = args;
201*4882a593Smuzhiyun irq_hw_number_t hwirq;
202*4882a593Smuzhiyun unsigned int type;
203*4882a593Smuzhiyun struct mbigen_device *mgn_chip;
204*4882a593Smuzhiyun int i, err;
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun err = mbigen_domain_translate(domain, fwspec, &hwirq, &type);
207*4882a593Smuzhiyun if (err)
208*4882a593Smuzhiyun return err;
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun err = platform_msi_domain_alloc(domain, virq, nr_irqs);
211*4882a593Smuzhiyun if (err)
212*4882a593Smuzhiyun return err;
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun mgn_chip = platform_msi_get_host_data(domain);
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun for (i = 0; i < nr_irqs; i++)
217*4882a593Smuzhiyun irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
218*4882a593Smuzhiyun &mbigen_irq_chip, mgn_chip->base);
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun return 0;
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun
mbigen_irq_domain_free(struct irq_domain * domain,unsigned int virq,unsigned int nr_irqs)223*4882a593Smuzhiyun static void mbigen_irq_domain_free(struct irq_domain *domain, unsigned int virq,
224*4882a593Smuzhiyun unsigned int nr_irqs)
225*4882a593Smuzhiyun {
226*4882a593Smuzhiyun platform_msi_domain_free(domain, virq, nr_irqs);
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun static const struct irq_domain_ops mbigen_domain_ops = {
230*4882a593Smuzhiyun .translate = mbigen_domain_translate,
231*4882a593Smuzhiyun .alloc = mbigen_irq_domain_alloc,
232*4882a593Smuzhiyun .free = mbigen_irq_domain_free,
233*4882a593Smuzhiyun };
234*4882a593Smuzhiyun
mbigen_of_create_domain(struct platform_device * pdev,struct mbigen_device * mgn_chip)235*4882a593Smuzhiyun static int mbigen_of_create_domain(struct platform_device *pdev,
236*4882a593Smuzhiyun struct mbigen_device *mgn_chip)
237*4882a593Smuzhiyun {
238*4882a593Smuzhiyun struct device *parent;
239*4882a593Smuzhiyun struct platform_device *child;
240*4882a593Smuzhiyun struct irq_domain *domain;
241*4882a593Smuzhiyun struct device_node *np;
242*4882a593Smuzhiyun u32 num_pins;
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun for_each_child_of_node(pdev->dev.of_node, np) {
245*4882a593Smuzhiyun if (!of_property_read_bool(np, "interrupt-controller"))
246*4882a593Smuzhiyun continue;
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun parent = platform_bus_type.dev_root;
249*4882a593Smuzhiyun child = of_platform_device_create(np, NULL, parent);
250*4882a593Smuzhiyun if (!child) {
251*4882a593Smuzhiyun of_node_put(np);
252*4882a593Smuzhiyun return -ENOMEM;
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun if (of_property_read_u32(child->dev.of_node, "num-pins",
256*4882a593Smuzhiyun &num_pins) < 0) {
257*4882a593Smuzhiyun dev_err(&pdev->dev, "No num-pins property\n");
258*4882a593Smuzhiyun of_node_put(np);
259*4882a593Smuzhiyun return -EINVAL;
260*4882a593Smuzhiyun }
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun domain = platform_msi_create_device_domain(&child->dev, num_pins,
263*4882a593Smuzhiyun mbigen_write_msg,
264*4882a593Smuzhiyun &mbigen_domain_ops,
265*4882a593Smuzhiyun mgn_chip);
266*4882a593Smuzhiyun if (!domain) {
267*4882a593Smuzhiyun of_node_put(np);
268*4882a593Smuzhiyun return -ENOMEM;
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun return 0;
273*4882a593Smuzhiyun }
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun #ifdef CONFIG_ACPI
mbigen_acpi_create_domain(struct platform_device * pdev,struct mbigen_device * mgn_chip)276*4882a593Smuzhiyun static int mbigen_acpi_create_domain(struct platform_device *pdev,
277*4882a593Smuzhiyun struct mbigen_device *mgn_chip)
278*4882a593Smuzhiyun {
279*4882a593Smuzhiyun struct irq_domain *domain;
280*4882a593Smuzhiyun u32 num_pins = 0;
281*4882a593Smuzhiyun int ret;
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun /*
284*4882a593Smuzhiyun * "num-pins" is the total number of interrupt pins implemented in
285*4882a593Smuzhiyun * this mbigen instance, and mbigen is an interrupt controller
286*4882a593Smuzhiyun * connected to ITS converting wired interrupts into MSI, so we
287*4882a593Smuzhiyun * use "num-pins" to alloc MSI vectors which are needed by client
288*4882a593Smuzhiyun * devices connected to it.
289*4882a593Smuzhiyun *
290*4882a593Smuzhiyun * Here is the DSDT device node used for mbigen in firmware:
291*4882a593Smuzhiyun * Device(MBI0) {
292*4882a593Smuzhiyun * Name(_HID, "HISI0152")
293*4882a593Smuzhiyun * Name(_UID, Zero)
294*4882a593Smuzhiyun * Name(_CRS, ResourceTemplate() {
295*4882a593Smuzhiyun * Memory32Fixed(ReadWrite, 0xa0080000, 0x10000)
296*4882a593Smuzhiyun * })
297*4882a593Smuzhiyun *
298*4882a593Smuzhiyun * Name(_DSD, Package () {
299*4882a593Smuzhiyun * ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
300*4882a593Smuzhiyun * Package () {
301*4882a593Smuzhiyun * Package () {"num-pins", 378}
302*4882a593Smuzhiyun * }
303*4882a593Smuzhiyun * })
304*4882a593Smuzhiyun * }
305*4882a593Smuzhiyun */
306*4882a593Smuzhiyun ret = device_property_read_u32(&pdev->dev, "num-pins", &num_pins);
307*4882a593Smuzhiyun if (ret || num_pins == 0)
308*4882a593Smuzhiyun return -EINVAL;
309*4882a593Smuzhiyun
310*4882a593Smuzhiyun domain = platform_msi_create_device_domain(&pdev->dev, num_pins,
311*4882a593Smuzhiyun mbigen_write_msg,
312*4882a593Smuzhiyun &mbigen_domain_ops,
313*4882a593Smuzhiyun mgn_chip);
314*4882a593Smuzhiyun if (!domain)
315*4882a593Smuzhiyun return -ENOMEM;
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun return 0;
318*4882a593Smuzhiyun }
319*4882a593Smuzhiyun #else
mbigen_acpi_create_domain(struct platform_device * pdev,struct mbigen_device * mgn_chip)320*4882a593Smuzhiyun static inline int mbigen_acpi_create_domain(struct platform_device *pdev,
321*4882a593Smuzhiyun struct mbigen_device *mgn_chip)
322*4882a593Smuzhiyun {
323*4882a593Smuzhiyun return -ENODEV;
324*4882a593Smuzhiyun }
325*4882a593Smuzhiyun #endif
326*4882a593Smuzhiyun
mbigen_device_probe(struct platform_device * pdev)327*4882a593Smuzhiyun static int mbigen_device_probe(struct platform_device *pdev)
328*4882a593Smuzhiyun {
329*4882a593Smuzhiyun struct mbigen_device *mgn_chip;
330*4882a593Smuzhiyun struct resource *res;
331*4882a593Smuzhiyun int err;
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun mgn_chip = devm_kzalloc(&pdev->dev, sizeof(*mgn_chip), GFP_KERNEL);
334*4882a593Smuzhiyun if (!mgn_chip)
335*4882a593Smuzhiyun return -ENOMEM;
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun mgn_chip->pdev = pdev;
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
340*4882a593Smuzhiyun if (!res)
341*4882a593Smuzhiyun return -EINVAL;
342*4882a593Smuzhiyun
343*4882a593Smuzhiyun mgn_chip->base = devm_ioremap(&pdev->dev, res->start,
344*4882a593Smuzhiyun resource_size(res));
345*4882a593Smuzhiyun if (!mgn_chip->base) {
346*4882a593Smuzhiyun dev_err(&pdev->dev, "failed to ioremap %pR\n", res);
347*4882a593Smuzhiyun return -ENOMEM;
348*4882a593Smuzhiyun }
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node)
351*4882a593Smuzhiyun err = mbigen_of_create_domain(pdev, mgn_chip);
352*4882a593Smuzhiyun else if (ACPI_COMPANION(&pdev->dev))
353*4882a593Smuzhiyun err = mbigen_acpi_create_domain(pdev, mgn_chip);
354*4882a593Smuzhiyun else
355*4882a593Smuzhiyun err = -EINVAL;
356*4882a593Smuzhiyun
357*4882a593Smuzhiyun if (err) {
358*4882a593Smuzhiyun dev_err(&pdev->dev, "Failed to create mbi-gen irqdomain\n");
359*4882a593Smuzhiyun return err;
360*4882a593Smuzhiyun }
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun platform_set_drvdata(pdev, mgn_chip);
363*4882a593Smuzhiyun return 0;
364*4882a593Smuzhiyun }
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun static const struct of_device_id mbigen_of_match[] = {
367*4882a593Smuzhiyun { .compatible = "hisilicon,mbigen-v2" },
368*4882a593Smuzhiyun { /* END */ }
369*4882a593Smuzhiyun };
370*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, mbigen_of_match);
371*4882a593Smuzhiyun
372*4882a593Smuzhiyun static const struct acpi_device_id mbigen_acpi_match[] = {
373*4882a593Smuzhiyun { "HISI0152", 0 },
374*4882a593Smuzhiyun {}
375*4882a593Smuzhiyun };
376*4882a593Smuzhiyun MODULE_DEVICE_TABLE(acpi, mbigen_acpi_match);
377*4882a593Smuzhiyun
378*4882a593Smuzhiyun static struct platform_driver mbigen_platform_driver = {
379*4882a593Smuzhiyun .driver = {
380*4882a593Smuzhiyun .name = "Hisilicon MBIGEN-V2",
381*4882a593Smuzhiyun .of_match_table = mbigen_of_match,
382*4882a593Smuzhiyun .acpi_match_table = ACPI_PTR(mbigen_acpi_match),
383*4882a593Smuzhiyun .suppress_bind_attrs = true,
384*4882a593Smuzhiyun },
385*4882a593Smuzhiyun .probe = mbigen_device_probe,
386*4882a593Smuzhiyun };
387*4882a593Smuzhiyun
388*4882a593Smuzhiyun module_platform_driver(mbigen_platform_driver);
389*4882a593Smuzhiyun
390*4882a593Smuzhiyun MODULE_AUTHOR("Jun Ma <majun258@huawei.com>");
391*4882a593Smuzhiyun MODULE_AUTHOR("Yun Wu <wuyun.wu@huawei.com>");
392*4882a593Smuzhiyun MODULE_LICENSE("GPL");
393*4882a593Smuzhiyun MODULE_DESCRIPTION("Hisilicon MBI Generator driver");
394