From: 张晴 Date: Tue, 29 Apr 2014 01:53:12 +0000 (+0800) Subject: rk3288:syb827:rename syb827 to syr82x for hardware modify X-Git-Tag: firefly_0821_release~5411 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=f415a98e9f385ae321884c0ba16ebbcd3bdf6a7b;p=firefly-linux-kernel-4.4.55.git rk3288:syb827:rename syb827 to syr82x for hardware modify --- diff --git a/arch/arm/boot/dts/rk3288-tb.dts b/arch/arm/boot/dts/rk3288-tb.dts index fb9daf6f1122..61945492476f 100755 --- a/arch/arm/boot/dts/rk3288-tb.dts +++ b/arch/arm/boot/dts/rk3288-tb.dts @@ -327,16 +327,16 @@ reg = <0x1c>; status = "okay"; }; - syb827b: syb827b@40 { - compatible = "silergy,syb827"; + syr827: syr827@40 { + compatible = "silergy,syr82x"; reg = <0x40>; status = "okay"; regulators { #address-cells = <1>; #size-cells = <0>; - syb827b_dc1: regulator@0 { + syr827_dc1: regulator@0 { reg = <0>; - regulator-compatible = "syb827_dcdc1"; + regulator-compatible = "syr82x_dcdc1"; regulator-name = "vdd_arm"; regulator-min-microvolt = <712500>; regulator-max-microvolt = <1500000>; @@ -352,16 +352,16 @@ }; }; }; - syb827c: syb827c@41 { - compatible = "silergy,syb827"; + syr828: syr828@41 { + compatible = "silergy,syr82x"; reg = <0x41>; status = "okay"; regulators { #address-cells = <1>; #size-cells = <0>; - syb827c_dc1: regulator@0 { + syr828_dc1: regulator@0 { reg = <0>; - regulator-compatible = "syb827_dcdc1"; + regulator-compatible = "syr82x_dcdc1"; regulator-name = "vdd_gpu"; regulator-min-microvolt = <712500>; regulator-max-microvolt = <1500000>; diff --git a/arch/arm/configs/rockchip_defconfig b/arch/arm/configs/rockchip_defconfig index 3e0b8e09814e..25bbd0cb062f 100755 --- a/arch/arm/configs/rockchip_defconfig +++ b/arch/arm/configs/rockchip_defconfig @@ -333,7 +333,7 @@ CONFIG_REGULATOR=y CONFIG_REGULATOR_FIXED_VOLTAGE=y CONFIG_REGULATOR_ACT8846=y CONFIG_ROCKCHIP_PWM_REGULATOR=y -CONFIG_REGULATOR_SYB827=y +CONFIG_REGULATOR_SYR82X=y CONFIG_REGULATOR_RICOH619=y CONFIG_MEDIA_SUPPORT=y CONFIG_MEDIA_CAMERA_SUPPORT=y diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index fdfde54afa41..a55583ce5012 100755 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -267,11 +267,11 @@ config ROCKCHIP_PWM_REGULATOR help Say Y to enable support for the voltage regulators control on the ROCKCHIP. -config REGULATOR_SYB827 - tristate "SYB827 DCDC SUPPORT REGULATOR" +config REGULATOR_SYR82X + tristate "SYR82X DCDC SUPPORT REGULATOR" depends on I2C help - Support the voltage and current regulators of the SYB827 series of DCDC devices. + Support the voltage and current regulators of the SYR82X series of DCDC devices. config REGULATOR_PCAP tristate "Motorola PCAP2 regulator driver" diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index d38b4658e8a0..e81fad7415c8 100755 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -74,7 +74,7 @@ obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o obj-$(CONFIG_REGULATOR_WM8994) += wm8994-regulator.o obj-$(CONFIG_REGULATOR_ACT8846) += act8846.o -obj-$(CONFIG_REGULATOR_SYB827) += syb827.o +obj-$(CONFIG_REGULATOR_SYR82X) += syr82x.o obj-$(CONFIG_REGULATOR_RICOH619) += ricoh619-regulator.o obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip_io_vol_domain.o diff --git a/drivers/regulator/syb827.c b/drivers/regulator/syb827.c deleted file mode 100755 index 5deee81604c8..000000000000 --- a/drivers/regulator/syb827.c +++ /dev/null @@ -1,586 +0,0 @@ -/* - * Regulator driver for syb827 DCDC chip for rk32xx - * - * Copyright (C) 2010, 2011 ROCKCHIP, Inc. - - * Based on syb827.c that is work by zhangqing - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if 0 -#define DBG(x...) printk(KERN_INFO x) -#else -#define DBG(x...) -#endif -#if 1 -#define DBG_INFO(x...) printk(KERN_INFO x) -#else -#define DBG_INFO(x...) -#endif -#define PM_CONTROL - -#define SYB827_SPEED 200*1000 -#define syb827_NUM_REGULATORS 1 - -struct syb827 { - struct device *dev; - struct mutex io_lock; - struct i2c_client *i2c; - int num_regulators; - struct regulator_dev **rdev; - int irq_base; - int chip_irq; - int sleep_gpio; /* */ - unsigned int dcdc_slp_voltage[3]; /* buckx_voltage in uV */ - bool pmic_sleep; - struct regmap *regmap; -}; - -struct syb827_regulator { - struct device *dev; - struct regulator_desc *desc; - struct regulator_dev *rdev; -}; -struct syb827_board { - int irq; - int irq_base; - struct regulator_init_data *syb827_init_data[syb827_NUM_REGULATORS]; - struct device_node *of_node[syb827_NUM_REGULATORS]; - int sleep_gpio; /* */ - unsigned int dcdc_slp_voltage[3]; /* buckx_voltage in uV */ - bool sleep; -}; - -struct syb827_regulator_subdev { - int id; - struct regulator_init_data *initdata; - struct device_node *reg_node; -}; - -struct syb827_platform_data { - int ono; - int num_regulators; - struct syb827_regulator_subdev *regulators; - - int sleep_gpio; /* */ - unsigned int dcdc_slp_voltage[3]; /* buckx_voltage in uV */ - bool sleep; -}; -struct syb827 *g_syb827; - -static u8 syb827_reg_read(struct syb827 *syb827, u8 reg); -static int syb827_set_bits(struct syb827 *syb827, u8 reg, u16 mask, u16 val); - - -#define SYB827_BUCK1_SET_VOL_BASE 0x00 -#define SYB827_BUCK1_SLP_VOL_BASE 0x01 -#define SYB827_CONTR_REG1 0x02 -#define SYB827_ID1_REG 0x03 -#define SYB827_ID2_REG 0x04 -#define SYB827_CONTR_REG2 0x05 - -#define BUCK_VOL_MASK 0x3f -#define VOL_MIN_IDX 0x00 -#define VOL_MAX_IDX 0x3f - -const static int buck_voltage_map[] = { - 712500, 725000, 737500,750000, 762500,775000,787500,800000, - 812500, 825000, 837500,850000, 862500,875000,887500,900000, - 912500, 925000, 937500,950000, 962500,975000,987500,1000000, - 1012500, 1025000, 1037500,1050000, 1062500,1075000,1087500,1100000, - 1112500, 1125000, 1137500,1150000, 1162500,1175000,1187500,1200000, - 1212500, 1225000, 1237500,1250000, 1262500,1275000,1287500,1300000, - 1312500, 1325000, 1337500,1350000, 1362500,1375000,1387500,1400000, - 1412500, 1425000, 1437500,1450000, 1462500,1475000,1487500,1500000, -}; - -static int syb827_dcdc_list_voltage(struct regulator_dev *dev, unsigned index) -{ - if (index >= ARRAY_SIZE(buck_voltage_map)) - return -EINVAL; - return buck_voltage_map[index]; -} -static int syb827_dcdc_is_enabled(struct regulator_dev *dev) -{ - struct syb827 *syb827 = rdev_get_drvdata(dev); - u16 val; - u16 mask=0x80; - val = syb827_reg_read(syb827, SYB827_BUCK1_SET_VOL_BASE); - if (val < 0) - return val; - val=val&~0x7f; - if (val & mask) - return 1; - else - return 0; -} -static int syb827_dcdc_enable(struct regulator_dev *dev) -{ - struct syb827 *syb827 = rdev_get_drvdata(dev); - u16 mask=0x80; - - return syb827_set_bits(syb827, SYB827_BUCK1_SET_VOL_BASE, mask, 0x80); - -} -static int syb827_dcdc_disable(struct regulator_dev *dev) -{ - struct syb827 *syb827 = rdev_get_drvdata(dev); - u16 mask=0x80; - return syb827_set_bits(syb827, SYB827_BUCK1_SET_VOL_BASE, mask, 0); -} -static int syb827_dcdc_get_voltage(struct regulator_dev *dev) -{ - struct syb827 *syb827 = rdev_get_drvdata(dev); - u16 reg = 0; - int val; - reg = syb827_reg_read(syb827,SYB827_BUCK1_SET_VOL_BASE); - reg &= BUCK_VOL_MASK; - val = buck_voltage_map[reg]; - return val; -} -static int syb827_dcdc_set_voltage(struct regulator_dev *dev, - int min_uV, int max_uV,unsigned *selector) -{ - struct syb827 *syb827 = rdev_get_drvdata(dev); - const int *vol_map = buck_voltage_map; - u16 val; - int ret = 0; - - if (min_uV < vol_map[VOL_MIN_IDX] || - min_uV > vol_map[VOL_MAX_IDX]) - return -EINVAL; - - for (val = VOL_MIN_IDX; val <= VOL_MAX_IDX; val++){ - if (vol_map[val] >= min_uV) - break; - } - - if (vol_map[val] > max_uV) - printk("WARNING:this voltage is not support!voltage set is %d mv\n",vol_map[val]); - - ret = syb827_set_bits(syb827, SYB827_BUCK1_SET_VOL_BASE ,BUCK_VOL_MASK, val); - - return ret; -} - -static unsigned int syb827_dcdc_get_mode(struct regulator_dev *dev) -{ - struct syb827 *syb827 = rdev_get_drvdata(dev); - u16 mask = 0x40; - u16 val; - val = syb827_reg_read(syb827, SYB827_BUCK1_SET_VOL_BASE); - if (val < 0) { - return val; - } - val=val & mask; - if (val== mask) - return REGULATOR_MODE_FAST; - else - return REGULATOR_MODE_NORMAL; - -} -static int syb827_dcdc_set_mode(struct regulator_dev *dev, unsigned int mode) -{ - struct syb827 *syb827 = rdev_get_drvdata(dev); - u16 mask = 0x40; - - switch(mode) - { - case REGULATOR_MODE_FAST: - return syb827_set_bits(syb827,SYB827_BUCK1_SET_VOL_BASE, mask, mask); - case REGULATOR_MODE_NORMAL: - return syb827_set_bits(syb827, SYB827_BUCK1_SET_VOL_BASE, mask, 0); - default: - printk("error:dcdc_syb827 only auto and pwm mode\n"); - return -EINVAL; - } -} -static int syb827_dcdc_set_voltage_time_sel(struct regulator_dev *dev, unsigned int old_selector, - unsigned int new_selector) -{ - int old_volt, new_volt; - - old_volt = syb827_dcdc_list_voltage(dev, old_selector); - if (old_volt < 0) - return old_volt; - - new_volt = syb827_dcdc_list_voltage(dev, new_selector); - if (new_volt < 0) - return new_volt; - - return DIV_ROUND_UP(abs(old_volt - new_volt)*4, 10000); -} -static int syb827_dcdc_suspend_enable(struct regulator_dev *dev) -{ - struct syb827 *syb827 = rdev_get_drvdata(dev); - u16 mask=0x80; - - return syb827_set_bits(syb827, SYB827_BUCK1_SLP_VOL_BASE, mask, 0x80); - -} -static int syb827_dcdc_suspend_disable(struct regulator_dev *dev) -{ - struct syb827 *syb827 = rdev_get_drvdata(dev); - u16 mask=0x80; - return syb827_set_bits(syb827, SYB827_BUCK1_SLP_VOL_BASE, mask, 0); -} -static int syb827_dcdc_set_sleep_voltage(struct regulator_dev *dev, - int uV) -{ - struct syb827 *syb827 = rdev_get_drvdata(dev); - const int *vol_map = buck_voltage_map; - u16 val; - int ret = 0; - - if (uV < vol_map[VOL_MIN_IDX] || - uV > vol_map[VOL_MAX_IDX]) - return -EINVAL; - - for (val = VOL_MIN_IDX; val <= VOL_MAX_IDX; val++){ - if (vol_map[val] >= uV) - break; - } - - if (vol_map[val] > uV) - printk("WARNING:this voltage is not support!voltage set is %d mv\n",vol_map[val]); - ret = syb827_set_bits(syb827,SYB827_BUCK1_SLP_VOL_BASE ,BUCK_VOL_MASK, val); - return ret; -} - - -static int syb827_dcdc_set_suspend_mode(struct regulator_dev *dev, unsigned int mode) -{ - struct syb827 *syb827 = rdev_get_drvdata(dev); - u16 mask = 0x40; - - switch(mode) - { - case REGULATOR_MODE_FAST: - return syb827_set_bits(syb827,SYB827_BUCK1_SLP_VOL_BASE, mask, mask); - case REGULATOR_MODE_NORMAL: - return syb827_set_bits(syb827, SYB827_BUCK1_SLP_VOL_BASE, mask, 0); - default: - printk("error:dcdc_syb827 only auto and pwm mode\n"); - return -EINVAL; - } -} - -static struct regulator_ops syb827_dcdc_ops = { - .set_voltage = syb827_dcdc_set_voltage, - .get_voltage = syb827_dcdc_get_voltage, - .list_voltage= syb827_dcdc_list_voltage, - .is_enabled = syb827_dcdc_is_enabled, - .enable = syb827_dcdc_enable, - .disable = syb827_dcdc_disable, - .get_mode = syb827_dcdc_get_mode, - .set_mode = syb827_dcdc_set_mode, - .set_suspend_voltage = syb827_dcdc_set_sleep_voltage, - .set_suspend_enable = syb827_dcdc_suspend_enable, - .set_suspend_disable = syb827_dcdc_suspend_disable, - .set_suspend_mode = syb827_dcdc_set_suspend_mode, - .set_voltage_time_sel = syb827_dcdc_set_voltage_time_sel, -}; -static struct regulator_desc regulators[] = { - - { - .name = "SY_DCDC1", - .id = 0, - .ops = &syb827_dcdc_ops, - .n_voltages = ARRAY_SIZE(buck_voltage_map), - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, - }, -}; - -static int syb827_i2c_read(struct i2c_client *i2c, char reg, int count, u16 *dest) -{ - int ret; - struct i2c_adapter *adap; - struct i2c_msg msgs[2]; - - if(!i2c) - return ret; - - if (count != 1) - return -EIO; - - adap = i2c->adapter; - - msgs[0].addr = i2c->addr; - msgs[0].buf = ® - msgs[0].flags = i2c->flags; - msgs[0].len = 1; - msgs[0].scl_rate = SYB827_SPEED; - - msgs[1].buf = (u8 *)dest; - msgs[1].addr = i2c->addr; - msgs[1].flags = i2c->flags | I2C_M_RD; - msgs[1].len = 1; - msgs[1].scl_rate = SYB827_SPEED; - ret = i2c_transfer(adap, msgs, 2); - - DBG("***run in %s %d msgs[1].buf = %d\n",__FUNCTION__,__LINE__,*(msgs[1].buf)); - - return 0; -} - -static int syb827_i2c_write(struct i2c_client *i2c, char reg, int count, const u16 src) -{ - int ret=-1; - - struct i2c_adapter *adap; - struct i2c_msg msg; - char tx_buf[2]; - - if(!i2c) - return ret; - if (count != 1) - return -EIO; - - adap = i2c->adapter; - tx_buf[0] = reg; - tx_buf[1] = src; - - msg.addr = i2c->addr; - msg.buf = &tx_buf[0]; - msg.len = 1 +1; - msg.flags = i2c->flags; - msg.scl_rate = SYB827_SPEED; - - ret = i2c_transfer(adap, &msg, 1); - return ret; -} - -static u8 syb827_reg_read(struct syb827 *syb827, u8 reg) -{ - u16 val = 0; - - mutex_lock(&syb827->io_lock); - - syb827_i2c_read(syb827->i2c, reg, 1, &val); - - DBG("reg read 0x%02x -> 0x%02x\n", (int)reg, (unsigned)val&0xff); - - mutex_unlock(&syb827->io_lock); - - return val & 0xff; -} - -static int syb827_set_bits(struct syb827 *syb827, u8 reg, u16 mask, u16 val) -{ - u16 tmp; - int ret; - - mutex_lock(&syb827->io_lock); - - ret = syb827_i2c_read(syb827->i2c, reg, 1, &tmp); - DBG("1 reg read 0x%02x -> 0x%02x\n", (int)reg, (unsigned)tmp&0xff); - tmp = (tmp & ~mask) | val; - if (ret == 0) { - ret = syb827_i2c_write(syb827->i2c, reg, 1, tmp); - DBG("reg write 0x%02x -> 0x%02x\n", (int)reg, (unsigned)val&0xff); - } - syb827_i2c_read(syb827->i2c, reg, 1, &tmp); - DBG("2 reg read 0x%02x -> 0x%02x\n", (int)reg, (unsigned)tmp&0xff); - mutex_unlock(&syb827->io_lock); - - return 0;//ret; -} - -#ifdef CONFIG_OF -static struct of_device_id syb827_of_match[] = { - { .compatible = "silergy,syb827"}, - { }, -}; -MODULE_DEVICE_TABLE(of, syb827_of_match); -#endif -#ifdef CONFIG_OF -static struct of_regulator_match syb827_reg_matches[] = { - { .name = "syb827_dcdc1" ,.driver_data = (void *)0}, -}; - -static struct syb827_board *syb827_parse_dt(struct syb827 *syb827) -{ - struct syb827_board *pdata; - struct device_node *regs; - struct device_node *syb827_np; - int gpio,count; - DBG("%s,line=%d\n", __func__,__LINE__); - - syb827_np = of_node_get(syb827->dev->of_node); - if (!syb827_np) { - printk("could not find pmic sub-node\n"); - return NULL; - } - - regs = of_find_node_by_name(syb827_np, "regulators"); - if (!regs) - return NULL; - count = of_regulator_match(syb827->dev, regs, syb827_reg_matches, - syb827_NUM_REGULATORS); - of_node_put(regs); - pdata = devm_kzalloc(syb827->dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return NULL; - pdata->syb827_init_data[0] = syb827_reg_matches[0].init_data; - pdata->of_node[0] = syb827_reg_matches[0].of_node; - - return pdata; -} - -#else -static struct syb827_board *syb827_parse_dt(struct i2c_client *i2c) -{ - return NULL; -} -#endif - -static int syb827_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) -{ - struct syb827 *syb827; - struct syb827_board *pdev ; - const struct of_device_id *match; - struct regulator_config config = { }; - struct regulator_dev *sy_rdev; - struct regulator_init_data *reg_data; - const char *rail_name = NULL; - int ret; - - DBG("%s,line=%d\n", __func__,__LINE__); - - if (i2c->dev.of_node) { - match = of_match_device(syb827_of_match, &i2c->dev); - if (!match) { - printk("Failed to find matching dt id\n"); - return -EINVAL; - } - } - - syb827 = devm_kzalloc(&i2c->dev,sizeof(struct syb827), GFP_KERNEL); - if (syb827 == NULL) { - ret = -ENOMEM; - goto err; - } - syb827->i2c = i2c; - syb827->dev = &i2c->dev; - i2c_set_clientdata(i2c, syb827); - g_syb827 = syb827; - - mutex_init(&syb827->io_lock); - - ret = syb827_reg_read(syb827,SYB827_ID1_REG); - if ((ret <0) ||(ret ==0xff) ||(ret ==0)){ - printk("The device is not syb827 %x \n",ret); - goto err; - } - - ret = syb827_set_bits(syb827,SYB827_CONTR_REG1,(1 << 6),(1<<6)); //10mv/2.4us - - if (syb827->dev->of_node) - pdev = syb827_parse_dt(syb827); - - if (pdev) { - syb827->num_regulators = syb827_NUM_REGULATORS; - syb827->rdev = kcalloc(syb827_NUM_REGULATORS,sizeof(struct regulator_dev *), GFP_KERNEL); - if (!syb827->rdev) { - return -ENOMEM; - } - /* Instantiate the regulators */ - reg_data = pdev->syb827_init_data[0]; - config.dev = syb827->dev; - config.driver_data = syb827; - if (syb827->dev->of_node) - config.of_node = pdev->of_node[0]; - if (reg_data && reg_data->constraints.name) - rail_name = reg_data->constraints.name; - else - rail_name = regulators[0].name; - reg_data->supply_regulator = rail_name; - - config.init_data =reg_data; - sy_rdev = regulator_register(®ulators[0],&config); - if (IS_ERR(sy_rdev)) { - printk("failed to register regulator\n"); - goto err; - } - syb827->rdev[0] = sy_rdev; - } - return 0; -err: - return ret; - -} - -static int syb827_i2c_remove(struct i2c_client *i2c) -{ - struct syb827 *syb827 = i2c_get_clientdata(i2c); - - if (syb827->rdev[0]) - regulator_unregister(syb827->rdev[0]); - i2c_set_clientdata(i2c, NULL); - return 0; -} - -static const struct i2c_device_id syb827_i2c_id[] = { - { "syb827", 0 }, - { } -}; - -MODULE_DEVICE_TABLE(i2c, syb827_i2c_id); - -static struct i2c_driver syb827_i2c_driver = { - .driver = { - .name = "syb827", - .owner = THIS_MODULE, - .of_match_table =of_match_ptr(syb827_of_match), - }, - .probe = syb827_i2c_probe, - .remove = syb827_i2c_remove, - .id_table = syb827_i2c_id, -}; - -static int __init syb827_module_init(void) -{ - int ret; - ret = i2c_add_driver(&syb827_i2c_driver); - if (ret != 0) - pr_err("Failed to register I2C driver: %d\n", ret); - return ret; -} -subsys_initcall_sync(syb827_module_init); - -static void __exit syb827_module_exit(void) -{ - i2c_del_driver(&syb827_i2c_driver); -} -module_exit(syb827_module_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("zhangqing "); -MODULE_DESCRIPTION("syb827 PMIC driver"); - diff --git a/drivers/regulator/syr82x.c b/drivers/regulator/syr82x.c new file mode 100755 index 000000000000..d700ef6675fd --- /dev/null +++ b/drivers/regulator/syr82x.c @@ -0,0 +1,586 @@ +/* + * Regulator driver for syr82x DCDC chip for rk32xx + * + * Copyright (C) 2010, 2011 ROCKCHIP, Inc. + + * Based on syr82x.c that is work by zhangqing + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if 0 +#define DBG(x...) printk(KERN_INFO x) +#else +#define DBG(x...) +#endif +#if 1 +#define DBG_INFO(x...) printk(KERN_INFO x) +#else +#define DBG_INFO(x...) +#endif +#define PM_CONTROL + +#define SYR82X_SPEED 200*1000 +#define syr82x_NUM_REGULATORS 1 + +struct syr82x { + struct device *dev; + struct mutex io_lock; + struct i2c_client *i2c; + int num_regulators; + struct regulator_dev **rdev; + int irq_base; + int chip_irq; + int sleep_gpio; /* */ + unsigned int dcdc_slp_voltage[3]; /* buckx_voltage in uV */ + bool pmic_sleep; + struct regmap *regmap; +}; + +struct syr82x_regulator { + struct device *dev; + struct regulator_desc *desc; + struct regulator_dev *rdev; +}; +struct syr82x_board { + int irq; + int irq_base; + struct regulator_init_data *syr82x_init_data[syr82x_NUM_REGULATORS]; + struct device_node *of_node[syr82x_NUM_REGULATORS]; + int sleep_gpio; /* */ + unsigned int dcdc_slp_voltage[3]; /* buckx_voltage in uV */ + bool sleep; +}; + +struct syr82x_regulator_subdev { + int id; + struct regulator_init_data *initdata; + struct device_node *reg_node; +}; + +struct syr82x_platform_data { + int ono; + int num_regulators; + struct syr82x_regulator_subdev *regulators; + + int sleep_gpio; /* */ + unsigned int dcdc_slp_voltage[3]; /* buckx_voltage in uV */ + bool sleep; +}; +struct syr82x *g_syr82x; + +static u8 syr82x_reg_read(struct syr82x *syr82x, u8 reg); +static int syr82x_set_bits(struct syr82x *syr82x, u8 reg, u16 mask, u16 val); + + +#define SYR82X_BUCK1_SET_VOL_BASE 0x00 +#define SYR82X_BUCK1_SLP_VOL_BASE 0x01 +#define SYR82X_CONTR_REG1 0x02 +#define SYR82X_ID1_REG 0x03 +#define SYR82X_ID2_REG 0x04 +#define SYR82X_CONTR_REG2 0x05 + +#define BUCK_VOL_MASK 0x3f +#define VOL_MIN_IDX 0x00 +#define VOL_MAX_IDX 0x3f + +const static int buck_voltage_map[] = { + 712500, 725000, 737500,750000, 762500,775000,787500,800000, + 812500, 825000, 837500,850000, 862500,875000,887500,900000, + 912500, 925000, 937500,950000, 962500,975000,987500,1000000, + 1012500, 1025000, 1037500,1050000, 1062500,1075000,1087500,1100000, + 1112500, 1125000, 1137500,1150000, 1162500,1175000,1187500,1200000, + 1212500, 1225000, 1237500,1250000, 1262500,1275000,1287500,1300000, + 1312500, 1325000, 1337500,1350000, 1362500,1375000,1387500,1400000, + 1412500, 1425000, 1437500,1450000, 1462500,1475000,1487500,1500000, +}; + +static int syr82x_dcdc_list_voltage(struct regulator_dev *dev, unsigned index) +{ + if (index >= ARRAY_SIZE(buck_voltage_map)) + return -EINVAL; + return buck_voltage_map[index]; +} +static int syr82x_dcdc_is_enabled(struct regulator_dev *dev) +{ + struct syr82x *syr82x = rdev_get_drvdata(dev); + u16 val; + u16 mask=0x80; + val = syr82x_reg_read(syr82x, SYR82X_BUCK1_SET_VOL_BASE); + if (val < 0) + return val; + val=val&~0x7f; + if (val & mask) + return 1; + else + return 0; +} +static int syr82x_dcdc_enable(struct regulator_dev *dev) +{ + struct syr82x *syr82x = rdev_get_drvdata(dev); + u16 mask=0x80; + + return syr82x_set_bits(syr82x, SYR82X_BUCK1_SET_VOL_BASE, mask, 0x80); + +} +static int syr82x_dcdc_disable(struct regulator_dev *dev) +{ + struct syr82x *syr82x = rdev_get_drvdata(dev); + u16 mask=0x80; + return syr82x_set_bits(syr82x, SYR82X_BUCK1_SET_VOL_BASE, mask, 0); +} +static int syr82x_dcdc_get_voltage(struct regulator_dev *dev) +{ + struct syr82x *syr82x = rdev_get_drvdata(dev); + u16 reg = 0; + int val; + reg = syr82x_reg_read(syr82x,SYR82X_BUCK1_SET_VOL_BASE); + reg &= BUCK_VOL_MASK; + val = buck_voltage_map[reg]; + return val; +} +static int syr82x_dcdc_set_voltage(struct regulator_dev *dev, + int min_uV, int max_uV,unsigned *selector) +{ + struct syr82x *syr82x = rdev_get_drvdata(dev); + const int *vol_map = buck_voltage_map; + u16 val; + int ret = 0; + + if (min_uV < vol_map[VOL_MIN_IDX] || + min_uV > vol_map[VOL_MAX_IDX]) + return -EINVAL; + + for (val = VOL_MIN_IDX; val <= VOL_MAX_IDX; val++){ + if (vol_map[val] >= min_uV) + break; + } + + if (vol_map[val] > max_uV) + printk("WARNING:this voltage is not support!voltage set is %d mv\n",vol_map[val]); + + ret = syr82x_set_bits(syr82x, SYR82X_BUCK1_SET_VOL_BASE ,BUCK_VOL_MASK, val); + + return ret; +} + +static unsigned int syr82x_dcdc_get_mode(struct regulator_dev *dev) +{ + struct syr82x *syr82x = rdev_get_drvdata(dev); + u16 mask = 0x40; + u16 val; + val = syr82x_reg_read(syr82x, SYR82X_BUCK1_SET_VOL_BASE); + if (val < 0) { + return val; + } + val=val & mask; + if (val== mask) + return REGULATOR_MODE_FAST; + else + return REGULATOR_MODE_NORMAL; + +} +static int syr82x_dcdc_set_mode(struct regulator_dev *dev, unsigned int mode) +{ + struct syr82x *syr82x = rdev_get_drvdata(dev); + u16 mask = 0x40; + + switch(mode) + { + case REGULATOR_MODE_FAST: + return syr82x_set_bits(syr82x,SYR82X_BUCK1_SET_VOL_BASE, mask, mask); + case REGULATOR_MODE_NORMAL: + return syr82x_set_bits(syr82x, SYR82X_BUCK1_SET_VOL_BASE, mask, 0); + default: + printk("error:dcdc_syr82x only auto and pwm mode\n"); + return -EINVAL; + } +} +static int syr82x_dcdc_set_voltage_time_sel(struct regulator_dev *dev, unsigned int old_selector, + unsigned int new_selector) +{ + int old_volt, new_volt; + + old_volt = syr82x_dcdc_list_voltage(dev, old_selector); + if (old_volt < 0) + return old_volt; + + new_volt = syr82x_dcdc_list_voltage(dev, new_selector); + if (new_volt < 0) + return new_volt; + + return DIV_ROUND_UP(abs(old_volt - new_volt)*4, 10000); +} +static int syr82x_dcdc_suspend_enable(struct regulator_dev *dev) +{ + struct syr82x *syr82x = rdev_get_drvdata(dev); + u16 mask=0x80; + + return syr82x_set_bits(syr82x, SYR82X_BUCK1_SLP_VOL_BASE, mask, 0x80); + +} +static int syr82x_dcdc_suspend_disable(struct regulator_dev *dev) +{ + struct syr82x *syr82x = rdev_get_drvdata(dev); + u16 mask=0x80; + return syr82x_set_bits(syr82x, SYR82X_BUCK1_SLP_VOL_BASE, mask, 0); +} +static int syr82x_dcdc_set_sleep_voltage(struct regulator_dev *dev, + int uV) +{ + struct syr82x *syr82x = rdev_get_drvdata(dev); + const int *vol_map = buck_voltage_map; + u16 val; + int ret = 0; + + if (uV < vol_map[VOL_MIN_IDX] || + uV > vol_map[VOL_MAX_IDX]) + return -EINVAL; + + for (val = VOL_MIN_IDX; val <= VOL_MAX_IDX; val++){ + if (vol_map[val] >= uV) + break; + } + + if (vol_map[val] > uV) + printk("WARNING:this voltage is not support!voltage set is %d mv\n",vol_map[val]); + ret = syr82x_set_bits(syr82x,SYR82X_BUCK1_SLP_VOL_BASE ,BUCK_VOL_MASK, val); + return ret; +} + + +static int syr82x_dcdc_set_suspend_mode(struct regulator_dev *dev, unsigned int mode) +{ + struct syr82x *syr82x = rdev_get_drvdata(dev); + u16 mask = 0x40; + + switch(mode) + { + case REGULATOR_MODE_FAST: + return syr82x_set_bits(syr82x,SYR82X_BUCK1_SLP_VOL_BASE, mask, mask); + case REGULATOR_MODE_NORMAL: + return syr82x_set_bits(syr82x, SYR82X_BUCK1_SLP_VOL_BASE, mask, 0); + default: + printk("error:dcdc_syr82x only auto and pwm mode\n"); + return -EINVAL; + } +} + +static struct regulator_ops syr82x_dcdc_ops = { + .set_voltage = syr82x_dcdc_set_voltage, + .get_voltage = syr82x_dcdc_get_voltage, + .list_voltage= syr82x_dcdc_list_voltage, + .is_enabled = syr82x_dcdc_is_enabled, + .enable = syr82x_dcdc_enable, + .disable = syr82x_dcdc_disable, + .get_mode = syr82x_dcdc_get_mode, + .set_mode = syr82x_dcdc_set_mode, + .set_suspend_voltage = syr82x_dcdc_set_sleep_voltage, + .set_suspend_enable = syr82x_dcdc_suspend_enable, + .set_suspend_disable = syr82x_dcdc_suspend_disable, + .set_suspend_mode = syr82x_dcdc_set_suspend_mode, + .set_voltage_time_sel = syr82x_dcdc_set_voltage_time_sel, +}; +static struct regulator_desc regulators[] = { + + { + .name = "SY_DCDC1", + .id = 0, + .ops = &syr82x_dcdc_ops, + .n_voltages = ARRAY_SIZE(buck_voltage_map), + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + }, +}; + +static int syr82x_i2c_read(struct i2c_client *i2c, char reg, int count, u16 *dest) +{ + int ret; + struct i2c_adapter *adap; + struct i2c_msg msgs[2]; + + if(!i2c) + return ret; + + if (count != 1) + return -EIO; + + adap = i2c->adapter; + + msgs[0].addr = i2c->addr; + msgs[0].buf = ® + msgs[0].flags = i2c->flags; + msgs[0].len = 1; + msgs[0].scl_rate = SYR82X_SPEED; + + msgs[1].buf = (u8 *)dest; + msgs[1].addr = i2c->addr; + msgs[1].flags = i2c->flags | I2C_M_RD; + msgs[1].len = 1; + msgs[1].scl_rate = SYR82X_SPEED; + ret = i2c_transfer(adap, msgs, 2); + + DBG("***run in %s %d msgs[1].buf = %d\n",__FUNCTION__,__LINE__,*(msgs[1].buf)); + + return 0; +} + +static int syr82x_i2c_write(struct i2c_client *i2c, char reg, int count, const u16 src) +{ + int ret=-1; + + struct i2c_adapter *adap; + struct i2c_msg msg; + char tx_buf[2]; + + if(!i2c) + return ret; + if (count != 1) + return -EIO; + + adap = i2c->adapter; + tx_buf[0] = reg; + tx_buf[1] = src; + + msg.addr = i2c->addr; + msg.buf = &tx_buf[0]; + msg.len = 1 +1; + msg.flags = i2c->flags; + msg.scl_rate = SYR82X_SPEED; + + ret = i2c_transfer(adap, &msg, 1); + return ret; +} + +static u8 syr82x_reg_read(struct syr82x *syr82x, u8 reg) +{ + u16 val = 0; + + mutex_lock(&syr82x->io_lock); + + syr82x_i2c_read(syr82x->i2c, reg, 1, &val); + + DBG("reg read 0x%02x -> 0x%02x\n", (int)reg, (unsigned)val&0xff); + + mutex_unlock(&syr82x->io_lock); + + return val & 0xff; +} + +static int syr82x_set_bits(struct syr82x *syr82x, u8 reg, u16 mask, u16 val) +{ + u16 tmp; + int ret; + + mutex_lock(&syr82x->io_lock); + + ret = syr82x_i2c_read(syr82x->i2c, reg, 1, &tmp); + DBG("1 reg read 0x%02x -> 0x%02x\n", (int)reg, (unsigned)tmp&0xff); + tmp = (tmp & ~mask) | val; + if (ret == 0) { + ret = syr82x_i2c_write(syr82x->i2c, reg, 1, tmp); + DBG("reg write 0x%02x -> 0x%02x\n", (int)reg, (unsigned)val&0xff); + } + syr82x_i2c_read(syr82x->i2c, reg, 1, &tmp); + DBG("2 reg read 0x%02x -> 0x%02x\n", (int)reg, (unsigned)tmp&0xff); + mutex_unlock(&syr82x->io_lock); + + return 0;//ret; +} + +#ifdef CONFIG_OF +static struct of_device_id syr82x_of_match[] = { + { .compatible = "silergy,syr82x"}, + { }, +}; +MODULE_DEVICE_TABLE(of, syr82x_of_match); +#endif +#ifdef CONFIG_OF +static struct of_regulator_match syr82x_reg_matches[] = { + { .name = "syr82x_dcdc1" ,.driver_data = (void *)0}, +}; + +static struct syr82x_board *syr82x_parse_dt(struct syr82x *syr82x) +{ + struct syr82x_board *pdata; + struct device_node *regs; + struct device_node *syr82x_np; + int gpio,count; + DBG("%s,line=%d\n", __func__,__LINE__); + + syr82x_np = of_node_get(syr82x->dev->of_node); + if (!syr82x_np) { + printk("could not find pmic sub-node\n"); + return NULL; + } + + regs = of_find_node_by_name(syr82x_np, "regulators"); + if (!regs) + return NULL; + count = of_regulator_match(syr82x->dev, regs, syr82x_reg_matches, + syr82x_NUM_REGULATORS); + of_node_put(regs); + pdata = devm_kzalloc(syr82x->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return NULL; + pdata->syr82x_init_data[0] = syr82x_reg_matches[0].init_data; + pdata->of_node[0] = syr82x_reg_matches[0].of_node; + + return pdata; +} + +#else +static struct syr82x_board *syr82x_parse_dt(struct i2c_client *i2c) +{ + return NULL; +} +#endif + +static int syr82x_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) +{ + struct syr82x *syr82x; + struct syr82x_board *pdev ; + const struct of_device_id *match; + struct regulator_config config = { }; + struct regulator_dev *sy_rdev; + struct regulator_init_data *reg_data; + const char *rail_name = NULL; + int ret; + + DBG("%s,line=%d\n", __func__,__LINE__); + + if (i2c->dev.of_node) { + match = of_match_device(syr82x_of_match, &i2c->dev); + if (!match) { + printk("Failed to find matching dt id\n"); + return -EINVAL; + } + } + + syr82x = devm_kzalloc(&i2c->dev,sizeof(struct syr82x), GFP_KERNEL); + if (syr82x == NULL) { + ret = -ENOMEM; + goto err; + } + syr82x->i2c = i2c; + syr82x->dev = &i2c->dev; + i2c_set_clientdata(i2c, syr82x); + g_syr82x = syr82x; + + mutex_init(&syr82x->io_lock); + + ret = syr82x_reg_read(syr82x,SYR82X_ID1_REG); + if ((ret <0) ||(ret ==0xff) ||(ret ==0)){ + printk("The device is not syr82x %x \n",ret); + goto err; + } + + ret = syr82x_set_bits(syr82x,SYR82X_CONTR_REG1,(1 << 6),(1<<6)); //10mv/2.4us + + if (syr82x->dev->of_node) + pdev = syr82x_parse_dt(syr82x); + + if (pdev) { + syr82x->num_regulators = syr82x_NUM_REGULATORS; + syr82x->rdev = kcalloc(syr82x_NUM_REGULATORS,sizeof(struct regulator_dev *), GFP_KERNEL); + if (!syr82x->rdev) { + return -ENOMEM; + } + /* Instantiate the regulators */ + reg_data = pdev->syr82x_init_data[0]; + config.dev = syr82x->dev; + config.driver_data = syr82x; + if (syr82x->dev->of_node) + config.of_node = pdev->of_node[0]; + if (reg_data && reg_data->constraints.name) + rail_name = reg_data->constraints.name; + else + rail_name = regulators[0].name; + reg_data->supply_regulator = rail_name; + + config.init_data =reg_data; + sy_rdev = regulator_register(®ulators[0],&config); + if (IS_ERR(sy_rdev)) { + printk("failed to register regulator\n"); + goto err; + } + syr82x->rdev[0] = sy_rdev; + } + return 0; +err: + return ret; + +} + +static int syr82x_i2c_remove(struct i2c_client *i2c) +{ + struct syr82x *syr82x = i2c_get_clientdata(i2c); + + if (syr82x->rdev[0]) + regulator_unregister(syr82x->rdev[0]); + i2c_set_clientdata(i2c, NULL); + return 0; +} + +static const struct i2c_device_id syr82x_i2c_id[] = { + { "syr82x", 0 }, + { } +}; + +MODULE_DEVICE_TABLE(i2c, syr82x_i2c_id); + +static struct i2c_driver syr82x_i2c_driver = { + .driver = { + .name = "syr82x", + .owner = THIS_MODULE, + .of_match_table =of_match_ptr(syr82x_of_match), + }, + .probe = syr82x_i2c_probe, + .remove = syr82x_i2c_remove, + .id_table = syr82x_i2c_id, +}; + +static int __init syr82x_module_init(void) +{ + int ret; + ret = i2c_add_driver(&syr82x_i2c_driver); + if (ret != 0) + pr_err("Failed to register I2C driver: %d\n", ret); + return ret; +} +subsys_initcall_sync(syr82x_module_init); + +static void __exit syr82x_module_exit(void) +{ + i2c_del_driver(&syr82x_i2c_driver); +} +module_exit(syr82x_module_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("zhangqing "); +MODULE_DESCRIPTION("syr82x PMIC driver"); +