]>
Commit | Line | Data |
---|---|---|
8bdf87b4 | 1 | /* |
ec58871f | 2 | * Device driver for Hi6421 PMIC |
8bdf87b4 GX |
3 | * |
4 | * Copyright (c) <2011-2014> HiSilicon Technologies Co., Ltd. | |
5 | * http://www.hisilicon.com | |
ec58871f | 6 | * Copyright (c) <2013-2017> Linaro Ltd. |
8bdf87b4 GX |
7 | * http://www.linaro.org |
8 | * | |
9 | * Author: Guodong Xu <[email protected]> | |
10 | * | |
11 | * This program is free software; you can redistribute it and/or modify | |
876368c3 GX |
12 | * it under the terms of the GNU General Public License version 2 as |
13 | * published by the Free Software Foundation. | |
8bdf87b4 GX |
14 | */ |
15 | ||
16 | #include <linux/device.h> | |
17 | #include <linux/err.h> | |
18 | #include <linux/mfd/core.h> | |
ec58871f | 19 | #include <linux/mfd/hi6421-pmic.h> |
8bdf87b4 | 20 | #include <linux/module.h> |
ec58871f | 21 | #include <linux/of_device.h> |
8bdf87b4 GX |
22 | #include <linux/platform_device.h> |
23 | #include <linux/regmap.h> | |
8bdf87b4 GX |
24 | |
25 | static const struct mfd_cell hi6421_devs[] = { | |
26 | { .name = "hi6421-regulator", }, | |
27 | }; | |
28 | ||
ec58871f GX |
29 | static const struct mfd_cell hi6421v530_devs[] = { |
30 | { .name = "hi6421v530-regulator", }, | |
31 | }; | |
32 | ||
7f9e3feb | 33 | static const struct regmap_config hi6421_regmap_config = { |
8bdf87b4 GX |
34 | .reg_bits = 32, |
35 | .reg_stride = 4, | |
36 | .val_bits = 8, | |
37 | .max_register = HI6421_REG_TO_BUS_ADDR(HI6421_REG_MAX), | |
38 | }; | |
39 | ||
ec58871f GX |
40 | static const struct of_device_id of_hi6421_pmic_match[] = { |
41 | { | |
42 | .compatible = "hisilicon,hi6421-pmic", | |
43 | .data = (void *)HI6421 | |
44 | }, | |
45 | { | |
46 | .compatible = "hisilicon,hi6421v530-pmic", | |
47 | .data = (void *)HI6421_V530 | |
48 | }, | |
49 | { }, | |
50 | }; | |
51 | MODULE_DEVICE_TABLE(of, of_hi6421_pmic_match); | |
52 | ||
8bdf87b4 GX |
53 | static int hi6421_pmic_probe(struct platform_device *pdev) |
54 | { | |
55 | struct hi6421_pmic *pmic; | |
56 | struct resource *res; | |
ec58871f GX |
57 | const struct of_device_id *id; |
58 | const struct mfd_cell *subdevs; | |
59 | enum hi6421_type type; | |
8bdf87b4 | 60 | void __iomem *base; |
ec58871f GX |
61 | int n_subdevs, ret; |
62 | ||
63 | id = of_match_device(of_hi6421_pmic_match, &pdev->dev); | |
64 | if (!id) | |
65 | return -EINVAL; | |
66 | type = (enum hi6421_type)id->data; | |
8bdf87b4 GX |
67 | |
68 | pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL); | |
69 | if (!pmic) | |
70 | return -ENOMEM; | |
71 | ||
72 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
73 | base = devm_ioremap_resource(&pdev->dev, res); | |
74 | if (IS_ERR(base)) | |
75 | return PTR_ERR(base); | |
76 | ||
77 | pmic->regmap = devm_regmap_init_mmio_clk(&pdev->dev, NULL, base, | |
78 | &hi6421_regmap_config); | |
79 | if (IS_ERR(pmic->regmap)) { | |
568e5476 GX |
80 | dev_err(&pdev->dev, "Failed to initialise Regmap: %ld\n", |
81 | PTR_ERR(pmic->regmap)); | |
8bdf87b4 GX |
82 | return PTR_ERR(pmic->regmap); |
83 | } | |
84 | ||
ec58871f GX |
85 | platform_set_drvdata(pdev, pmic); |
86 | ||
87 | switch (type) { | |
88 | case HI6421: | |
89 | /* set over-current protection debounce 8ms */ | |
90 | regmap_update_bits(pmic->regmap, HI6421_OCP_DEB_CTRL_REG, | |
8bdf87b4 GX |
91 | (HI6421_OCP_DEB_SEL_MASK |
92 | | HI6421_OCP_EN_DEBOUNCE_MASK | |
93 | | HI6421_OCP_AUTO_STOP_MASK), | |
94 | (HI6421_OCP_DEB_SEL_8MS | |
95 | | HI6421_OCP_EN_DEBOUNCE_ENABLE)); | |
96 | ||
ec58871f GX |
97 | subdevs = hi6421_devs; |
98 | n_subdevs = ARRAY_SIZE(hi6421_devs); | |
99 | break; | |
100 | case HI6421_V530: | |
101 | subdevs = hi6421v530_devs; | |
102 | n_subdevs = ARRAY_SIZE(hi6421v530_devs); | |
103 | break; | |
104 | default: | |
105 | dev_err(&pdev->dev, "Unknown device type %d\n", | |
106 | (unsigned int)type); | |
107 | return -EINVAL; | |
108 | } | |
8bdf87b4 | 109 | |
ec58871f GX |
110 | ret = devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, |
111 | subdevs, n_subdevs, NULL, 0, NULL); | |
8bdf87b4 | 112 | if (ret) { |
568e5476 | 113 | dev_err(&pdev->dev, "Failed to add child devices: %d\n", ret); |
8bdf87b4 GX |
114 | return ret; |
115 | } | |
116 | ||
117 | return 0; | |
118 | } | |
119 | ||
8bdf87b4 GX |
120 | static struct platform_driver hi6421_pmic_driver = { |
121 | .driver = { | |
ec58871f GX |
122 | .name = "hi6421_pmic", |
123 | .of_match_table = of_hi6421_pmic_match, | |
8bdf87b4 GX |
124 | }, |
125 | .probe = hi6421_pmic_probe, | |
8bdf87b4 GX |
126 | }; |
127 | module_platform_driver(hi6421_pmic_driver); | |
128 | ||
129 | MODULE_AUTHOR("Guodong Xu <[email protected]>"); | |
130 | MODULE_DESCRIPTION("Hi6421 PMIC driver"); | |
131 | MODULE_LICENSE("GPL v2"); |