1111#include <linux/platform_device.h>
1212#include <linux/slab.h>
1313
14- #define VREG_STATE 2
14+ #define VREG_STATE 2
15+ #define VREG_GRP 0
1516#define TWL6030_CFG_STATE_OFF 0x00
1617#define TWL6030_CFG_STATE_ON 0x01
1718#define TWL6030_CFG_STATE_MASK 0x03
19+ #define TWL6030_CFG_STATE_GRP_SHIFT 5
20+ #define TWL6030_CFG_STATE_APP_SHIFT 2
21+ #define TWL6030_CFG_STATE_APP_MASK (0x03 << TWL6030_CFG_STATE_APP_SHIFT)
22+ #define TWL6030_CFG_STATE_APP (v ) (((v) & TWL6030_CFG_STATE_APP_MASK) >>\
23+ TWL6030_CFG_STATE_APP_SHIFT)
24+ #define P1_GRP BIT(0) /* processor power group */
25+ #define P2_GRP BIT(1)
26+ #define P3_GRP BIT(2)
27+ #define ALL_GRP (P1_GRP | P2_GRP | P3_GRP)
28+
29+ enum twl_type {
30+ TWL_TYPE_6030 ,
31+ TWL_TYPE_6032 ,
32+ };
1833
1934struct twl_clock_info {
2035 struct device * dev ;
36+ enum twl_type type ;
2137 u8 base ;
2238 struct clk_hw hw ;
2339};
@@ -56,23 +72,36 @@ static unsigned long twl_clks_recalc_rate(struct clk_hw *hw,
5672static int twl6032_clks_prepare (struct clk_hw * hw )
5773{
5874 struct twl_clock_info * cinfo = to_twl_clks_info (hw );
59- int ret ;
6075
61- ret = twlclk_write (cinfo , TWL_MODULE_PM_RECEIVER , VREG_STATE ,
62- TWL6030_CFG_STATE_ON );
63- if (ret < 0 )
64- dev_err (cinfo -> dev , "clk prepare failed\n" );
76+ if (cinfo -> type == TWL_TYPE_6030 ) {
77+ int grp ;
78+
79+ grp = twlclk_read (cinfo , TWL_MODULE_PM_RECEIVER , VREG_GRP );
80+ if (grp < 0 )
81+ return grp ;
6582
66- return ret ;
83+ return twlclk_write (cinfo , TWL_MODULE_PM_RECEIVER , VREG_STATE ,
84+ grp << TWL6030_CFG_STATE_GRP_SHIFT |
85+ TWL6030_CFG_STATE_ON );
86+ }
87+
88+ return twlclk_write (cinfo , TWL_MODULE_PM_RECEIVER , VREG_STATE ,
89+ TWL6030_CFG_STATE_ON );
6790}
6891
6992static void twl6032_clks_unprepare (struct clk_hw * hw )
7093{
7194 struct twl_clock_info * cinfo = to_twl_clks_info (hw );
7295 int ret ;
7396
74- ret = twlclk_write (cinfo , TWL_MODULE_PM_RECEIVER , VREG_STATE ,
75- TWL6030_CFG_STATE_OFF );
97+ if (cinfo -> type == TWL_TYPE_6030 )
98+ ret = twlclk_write (cinfo , TWL_MODULE_PM_RECEIVER , VREG_STATE ,
99+ ALL_GRP << TWL6030_CFG_STATE_GRP_SHIFT |
100+ TWL6030_CFG_STATE_OFF );
101+ else
102+ ret = twlclk_write (cinfo , TWL_MODULE_PM_RECEIVER , VREG_STATE ,
103+ TWL6030_CFG_STATE_OFF );
104+
76105 if (ret < 0 )
77106 dev_err (cinfo -> dev , "clk unprepare failed\n" );
78107}
@@ -138,6 +167,7 @@ static int twl_clks_probe(struct platform_device *pdev)
138167 for (i = 0 ; i < count ; i ++ ) {
139168 cinfo [i ].base = hw_data [i ].base ;
140169 cinfo [i ].dev = & pdev -> dev ;
170+ cinfo [i ].type = platform_get_device_id (pdev )-> driver_data ;
141171 cinfo [i ].hw .init = & hw_data [i ].init ;
142172 ret = devm_clk_hw_register (& pdev -> dev , & cinfo [i ].hw );
143173 if (ret ) {
@@ -159,7 +189,11 @@ static int twl_clks_probe(struct platform_device *pdev)
159189
160190static const struct platform_device_id twl_clks_id [] = {
161191 {
192+ .name = "twl6030-clk" ,
193+ .driver_data = TWL_TYPE_6030 ,
194+ }, {
162195 .name = "twl6032-clk" ,
196+ .driver_data = TWL_TYPE_6032 ,
163197 }, {
164198 /* sentinel */
165199 }
0 commit comments