/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (c) 2021 MediaTek Inc. */ #include #include #include #include #include #include #include "../../flashlight/richtek/rtfled.h" #include "inc/mt6370_pmu.h" #include "inc/mt6370_pmu_fled.h" #include "inc/mt6370_pmu_charger.h" #define MT6370_PMU_FLED_DRV_VERSION "1.0.3_MTK" static DEFINE_MUTEX(fled_lock); static u8 mt6370_fled_inited; static u8 mt6370_global_mode = FLASHLIGHT_MODE_OFF; static u8 mt6370_fled_on; enum { MT6370_FLED1 = 0, MT6370_FLED2 = 1, }; struct mt6370_pmu_fled_data { struct rt_fled_dev base; struct mt6370_pmu_chip *chip; struct device *dev; struct platform_device *mt_flash_dev; int id; unsigned char suspend:1; unsigned char fled_ctrl:2; /* fled1, fled2, both */ unsigned char fled_ctrl_reg; unsigned char fled_tor_cur_reg; unsigned char fled_strb_cur_reg; unsigned char fled_strb_to_reg; unsigned char fled_cs_mask; }; static const char *flashlight_mode_str[FLASHLIGHT_MODE_MAX] = { "off", "torch", "flash", "mixed", "dual flash", "dual torch", "dual off", }; static irqreturn_t mt6370_pmu_fled_strbpin_irq_handler(int irq, void *data) { return IRQ_HANDLED; } static irqreturn_t mt6370_pmu_fled_torpin_irq_handler(int irq, void *data) { return IRQ_HANDLED; } static irqreturn_t mt6370_pmu_fled_tx_irq_handler(int irq, void *data) { return IRQ_HANDLED; } static irqreturn_t mt6370_pmu_fled_lvf_irq_handler(int irq, void *data) { struct mt6370_pmu_fled_data *info = data; dev_notice(info->dev, "%s\n", __func__); return IRQ_HANDLED; } static irqreturn_t mt6370_pmu_fled2_short_irq_handler(int irq, void *data) { struct mt6370_pmu_fled_data *info = data; dev_notice(info->dev, "%s\n", __func__); return IRQ_HANDLED; } static irqreturn_t mt6370_pmu_fled1_short_irq_handler(int irq, void *data) { struct mt6370_pmu_fled_data *info = data; dev_notice(info->dev, "%s\n", __func__); return IRQ_HANDLED; } static irqreturn_t mt6370_pmu_fled2_strb_irq_handler(int irq, void *data) { return IRQ_HANDLED; } static irqreturn_t mt6370_pmu_fled1_strb_irq_handler(int irq, void *data) { return IRQ_HANDLED; } static irqreturn_t mt6370_pmu_fled2_strb_to_irq_handler(int irq, void *data) { struct mt6370_pmu_fled_data *fi = (struct mt6370_pmu_fled_data *)data; dev_info(fi->dev, "%s occurred\n", __func__); return IRQ_HANDLED; } static irqreturn_t mt6370_pmu_fled1_strb_to_irq_handler(int irq, void *data) { struct mt6370_pmu_fled_data *fi = (struct mt6370_pmu_fled_data *)data; dev_info(fi->dev, "%s occurred\n", __func__); return IRQ_HANDLED; } static irqreturn_t mt6370_pmu_fled2_tor_irq_handler(int irq, void *data) { return IRQ_HANDLED; } static irqreturn_t mt6370_pmu_fled1_tor_irq_handler(int irq, void *data) { return IRQ_HANDLED; } static struct mt6370_pmu_irq_desc mt6370_fled_irq_desc[] = { MT6370_PMU_IRQDESC(fled_strbpin), MT6370_PMU_IRQDESC(fled_torpin), MT6370_PMU_IRQDESC(fled_tx), MT6370_PMU_IRQDESC(fled_lvf), MT6370_PMU_IRQDESC(fled2_short), MT6370_PMU_IRQDESC(fled1_short), MT6370_PMU_IRQDESC(fled2_strb), MT6370_PMU_IRQDESC(fled1_strb), MT6370_PMU_IRQDESC(fled2_strb_to), MT6370_PMU_IRQDESC(fled1_strb_to), MT6370_PMU_IRQDESC(fled2_tor), MT6370_PMU_IRQDESC(fled1_tor), }; static void mt6370_pmu_fled_irq_register(struct platform_device *pdev) { struct resource *res; int i, ret = 0; for (i = 0; i < ARRAY_SIZE(mt6370_fled_irq_desc); i++) { if (!mt6370_fled_irq_desc[i].name) continue; res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, mt6370_fled_irq_desc[i].name); if (!res) continue; ret = devm_request_threaded_irq(&pdev->dev, res->start, NULL, mt6370_fled_irq_desc[i].irq_handler, IRQF_TRIGGER_FALLING, mt6370_fled_irq_desc[i].name, platform_get_drvdata(pdev)); if (ret < 0) { dev_err(&pdev->dev, "request %s irq fail\n", res->name); continue; } mt6370_fled_irq_desc[i].irq = res->start; } } static inline int mt6370_fled_parse_dt(struct device *dev, struct mt6370_pmu_fled_data *fi) { struct device_node *np = dev->of_node; int ret = 0; u32 val = 0; unsigned char regval; pr_info("%s start\n", __func__); if (!np) { pr_err("%s cannot mt6370 fled dts node\n", __func__); return -ENODEV; } #if 0 ret = of_property_read_u32(np, "fled_enable", &val); if (ret < 0) { pr_err("%s default enable fled%d\n", __func__, fi->id+1); } else { if (val) { pr_info("%s enable fled%d\n", __func__, fi->id+1); mt6370_pmu_reg_set_bit(fi->chip, MT6370_PMU_REG_FLEDEN, fi->fled_cs_mask); } else { pr_info("%s disable fled%d\n", __func__, fi->id+1); mt6370_pmu_reg_clr_bit(fi->chip, MT6370_PMU_REG_FLEDEN, fi->fled_cs_mask); } } #endif ret = of_property_read_u32(np, "torch_cur", &val); if (ret < 0) pr_err("%s use default torch cur\n", __func__); else { pr_info("%s use torch cur %d\n", __func__, val); regval = (val > 400000) ? 30 : (val - 25000)/12500; mt6370_pmu_reg_update_bits(fi->chip, fi->fled_tor_cur_reg, MT6370_FLED_TORCHCUR_MASK, regval << MT6370_FLED_TORCHCUR_SHIFT); } ret = of_property_read_u32(np, "strobe_cur", &val); if (ret < 0) pr_err("%s use default strobe cur\n", __func__); else { pr_info("%s use strobe cur %d\n", __func__, val); regval = (val > 1500000) ? 112 : (val - 100000)/12500; mt6370_pmu_reg_update_bits(fi->chip, fi->fled_strb_cur_reg, MT6370_FLED_STROBECUR_MASK, regval << MT6370_FLED_STROBECUR_SHIFT); } ret = of_property_read_u32(np, "strobe_timeout", &val); if (ret < 0) pr_err("%s use default strobe timeout\n", __func__); else { pr_info("%s use strobe timeout %d\n", __func__, val); regval = (val > 2432) ? 74 : (val - 64)/32; mt6370_pmu_reg_update_bits(fi->chip, MT6370_PMU_REG_FLEDSTRBCTRL, MT6370_FLED_STROBE_TIMEOUT_MASK, regval << MT6370_FLED_STROBE_TIMEOUT_SHIFT); } return 0; } static struct flashlight_properties mt6370_fled_props = { .type = FLASHLIGHT_TYPE_LED, .torch_brightness = 0, .torch_max_brightness = 30, /* 00000 ~ 11110 */ .strobe_brightness = 0, .strobe_max_brightness = 255, /* 0000000 ~ 1111111 */ .strobe_delay = 0, .strobe_timeout = 0, .alias_name = "mt6370-fled", }; static int mt6370_fled_reg_init(struct mt6370_pmu_fled_data *info) { /* TBD */ return 0; } static int mt6370_fled_init(struct rt_fled_dev *info) { struct mt6370_pmu_fled_data *fi = (struct mt6370_pmu_fled_data *)info; int ret = 0; ret = mt6370_fled_reg_init(fi); if (ret < 0) dev_err(fi->dev, "init mt6370 fled register fail\n"); return ret; } static int mt6370_fled_suspend(struct rt_fled_dev *info, pm_message_t state) { struct mt6370_pmu_fled_data *fi = (struct mt6370_pmu_fled_data *)info; fi->suspend = 1; return 0; } static int mt6370_fled_resume(struct rt_fled_dev *info) { struct mt6370_pmu_fled_data *fi = (struct mt6370_pmu_fled_data *)info; fi->suspend = 0; return 0; } static int mt6370_fled_set_mode(struct rt_fled_dev *info, enum flashlight_mode mode) { struct mt6370_pmu_fled_data *fi = (struct mt6370_pmu_fled_data *)info; int ret = 0; u8 val, mask; bool hz_en = false, cfo_en = true; switch (mode) { case FLASHLIGHT_MODE_FLASH: case FLASHLIGHT_MODE_DUAL_FLASH: ret = mt6370_pmu_reg_test_bit(fi->chip, MT6370_PMU_REG_CHGCTRL1, MT6370_SHIFT_HZ_EN, &hz_en); if (ret >= 0 && hz_en) { dev_err(fi->dev, "%s WARNING\n", __func__); dev_err(fi->dev, "%s set %s mode with HZ=1\n", __func__, flashlight_mode_str[mode]); } ret = mt6370_pmu_reg_test_bit(fi->chip, MT6370_PMU_REG_CHGCTRL2, MT6370_SHIFT_CFO_EN, &cfo_en); if (ret >= 0 && !cfo_en) { dev_err(fi->dev, "%s WARNING\n", __func__); dev_err(fi->dev, "%s set %s mode with CFO=0\n", __func__, flashlight_mode_str[mode]); } break; default: break; } mutex_lock(&fled_lock); switch (mode) { case FLASHLIGHT_MODE_TORCH: if (mt6370_global_mode == FLASHLIGHT_MODE_FLASH) break; ret |= mt6370_pmu_reg_clr_bit(fi->chip, MT6370_PMU_REG_FLEDEN, MT6370_STROBE_EN_MASK); udelay(500); ret |= mt6370_pmu_reg_set_bit(fi->chip, MT6370_PMU_REG_FLEDEN, fi->id == MT6370_FLED1 ? 0x02 : 0x01); ret |= mt6370_pmu_reg_set_bit(fi->chip, MT6370_PMU_REG_FLEDEN, MT6370_TORCH_EN_MASK); udelay(500); dev_info(fi->dev, "set to torch mode with 500 us delay\n"); mt6370_global_mode = mode; if (fi->id == MT6370_FLED1) mt6370_fled_on |= 1 << MT6370_FLED1; if (fi->id == MT6370_FLED2) mt6370_fled_on |= 1 << MT6370_FLED2; break; case FLASHLIGHT_MODE_FLASH: ret = mt6370_pmu_reg_clr_bit(fi->chip, MT6370_PMU_REG_FLEDEN, MT6370_STROBE_EN_MASK); udelay(400); ret |= mt6370_pmu_reg_set_bit(fi->chip, MT6370_PMU_REG_FLEDEN, fi->id == MT6370_FLED1 ? 0x02 : 0x01); ret |= mt6370_pmu_reg_set_bit(fi->chip, MT6370_PMU_REG_FLEDEN, MT6370_STROBE_EN_MASK); mdelay(5); dev_info(fi->dev, "set to flash mode with 400/4500 us delay\n"); mt6370_global_mode = mode; if (fi->id == MT6370_FLED1) mt6370_fled_on |= 1 << MT6370_FLED1; if (fi->id == MT6370_FLED2) mt6370_fled_on |= 1 << MT6370_FLED2; break; case FLASHLIGHT_MODE_OFF: ret = mt6370_pmu_reg_clr_bit(fi->chip, MT6370_PMU_REG_FLEDEN, fi->id == MT6370_FLED1 ? 0x02 : 0x01); dev_info(fi->dev, "set to off mode\n"); if (fi->id == MT6370_FLED1) mt6370_fled_on &= ~(1 << MT6370_FLED1); if (fi->id == MT6370_FLED2) mt6370_fled_on &= ~(1 << MT6370_FLED2); if (mt6370_fled_on == 0) mt6370_global_mode = mode; break; case FLASHLIGHT_MODE_DUAL_FLASH: if (fi->id == MT6370_FLED2) goto out; /* strobe off */ ret = mt6370_pmu_reg_clr_bit(fi->chip, MT6370_PMU_REG_FLEDEN, MT6370_STROBE_EN_MASK); if (ret < 0) break; udelay(400); /* fled en/strobe on */ val = BIT(MT6370_FLED1) | BIT(MT6370_FLED2) | MT6370_STROBE_EN_MASK; mask = val; ret = mt6370_pmu_reg_update_bits(fi->chip, MT6370_PMU_REG_FLEDEN, mask, val); if (ret < 0) break; mt6370_global_mode = mode; mt6370_fled_on |= (BIT(MT6370_FLED1) | BIT(MT6370_FLED2)); break; case FLASHLIGHT_MODE_DUAL_TORCH: if (fi->id == MT6370_FLED2) goto out; if (mt6370_global_mode == FLASHLIGHT_MODE_FLASH || mt6370_global_mode == FLASHLIGHT_MODE_DUAL_FLASH) goto out; /* Fled en/Strobe off/Torch on */ ret = mt6370_pmu_reg_clr_bit(fi->chip, MT6370_PMU_REG_FLEDEN, MT6370_STROBE_EN_MASK); if (ret < 0) break; udelay(500); val = BIT(MT6370_FLED1) | BIT(MT6370_FLED2) | MT6370_TORCH_EN_MASK; ret = mt6370_pmu_reg_set_bit(fi->chip, MT6370_PMU_REG_FLEDEN, val); if (ret < 0) break; udelay(500); mt6370_global_mode = mode; mt6370_fled_on |= (BIT(MT6370_FLED1) | BIT(MT6370_FLED2)); break; case FLASHLIGHT_MODE_DUAL_OFF: if (fi->id == MT6370_FLED2) goto out; ret = mt6370_pmu_reg_clr_bit(fi->chip, MT6370_PMU_REG_FLEDEN, BIT(MT6370_FLED1) | BIT(MT6370_FLED2)); if (ret < 0) break; mt6370_fled_on = 0; mt6370_global_mode = FLASHLIGHT_MODE_OFF; break; default: mutex_unlock(&fled_lock); return -EINVAL; } if (ret < 0) dev_info(fi->dev, "%s set %s mode fail\n", __func__, flashlight_mode_str[mode]); else dev_info(fi->dev, "%s set %s\n", __func__, flashlight_mode_str[mode]); out: mutex_unlock(&fled_lock); return ret; } static int mt6370_fled_get_mode(struct rt_fled_dev *info) { struct mt6370_pmu_fled_data *fi = (struct mt6370_pmu_fled_data *)info; int ret; if (fi->id == MT6370_FLED2) { pr_err("%s FLED2 not support get mode\n", __func__); return 0; } ret = mt6370_pmu_reg_read(fi->chip, MT6370_PMU_REG_FLEDEN); if (ret < 0) return -EINVAL; if (ret & MT6370_STROBE_EN_MASK) return FLASHLIGHT_MODE_FLASH; else if (ret & MT6370_TORCH_EN_MASK) return FLASHLIGHT_MODE_TORCH; else return FLASHLIGHT_MODE_OFF; } static int mt6370_fled_strobe(struct rt_fled_dev *info) { return mt6370_fled_set_mode(info, FLASHLIGHT_MODE_FLASH); } static int mt6370_fled_torch_current_list( struct rt_fled_dev *info, int selector) { struct mt6370_pmu_fled_data *fi = (struct mt6370_pmu_fled_data *)info; return (selector > fi->base.init_props->torch_max_brightness) ? -EINVAL : 25000 + selector * 12500; } static int mt6370_fled_strobe_current_list(struct rt_fled_dev *info, int selector) { struct mt6370_pmu_fled_data *fi = (struct mt6370_pmu_fled_data *)info; if (selector > fi->base.init_props->strobe_max_brightness) return -EINVAL; if (selector < 128) return 50000 + selector * 12500; else return 25000 + (selector - 128) * 6250; } static unsigned int mt6370_timeout_level_list[] = { 50000, 75000, 100000, 125000, 150000, 175000, 200000, 200000, }; static int mt6370_fled_timeout_level_list(struct rt_fled_dev *info, int selector) { return (selector >= ARRAY_SIZE(mt6370_timeout_level_list)) ? -EINVAL : mt6370_timeout_level_list[selector]; } static int mt6370_fled_strobe_timeout_list(struct rt_fled_dev *info, int selector) { if (selector > 74) return -EINVAL; return 64 + selector * 32; } static int mt6370_fled_set_torch_current_sel(struct rt_fled_dev *info, int selector) { struct mt6370_pmu_fled_data *fi = (struct mt6370_pmu_fled_data *)info; int ret; ret = mt6370_pmu_reg_update_bits(fi->chip, fi->fled_tor_cur_reg, MT6370_FLED_TORCHCUR_MASK, selector << MT6370_FLED_TORCHCUR_SHIFT); return ret; } static int mt6370_fled_set_strobe_current_sel(struct rt_fled_dev *info, int selector) { struct mt6370_pmu_fled_data *fi = (struct mt6370_pmu_fled_data *)info; int ret; if (selector > fi->base.init_props->strobe_max_brightness) return -EINVAL; if (selector < 128) mt6370_pmu_reg_clr_bit(fi->chip, fi->fled_strb_cur_reg, 0x80); else mt6370_pmu_reg_set_bit(fi->chip, fi->fled_strb_cur_reg, 0x80); if (selector >= 128) selector -= 128; ret = mt6370_pmu_reg_update_bits(fi->chip, fi->fled_strb_cur_reg, MT6370_FLED_STROBECUR_MASK, selector << MT6370_FLED_STROBECUR_SHIFT); return ret; } static int mt6370_fled_set_timeout_level_sel(struct rt_fled_dev *info, int selector) { struct mt6370_pmu_fled_data *fi = (struct mt6370_pmu_fled_data *)info; int ret; if (fi->id == MT6370_FLED1) { ret = mt6370_pmu_reg_update_bits(fi->chip, MT6370_PMU_REG_FLED1CTRL, MT6370_FLED_TIMEOUT_LEVEL_MASK, selector << MT6370_TIMEOUT_LEVEL_SHIFT); } else { ret = mt6370_pmu_reg_update_bits(fi->chip, MT6370_PMU_REG_FLED2CTRL, MT6370_FLED_TIMEOUT_LEVEL_MASK, selector << MT6370_TIMEOUT_LEVEL_SHIFT); } return ret; } static int mt6370_fled_set_strobe_timeout_sel(struct rt_fled_dev *info, int selector) { struct mt6370_pmu_fled_data *fi = (struct mt6370_pmu_fled_data *)info; int ret = 0; if (fi->id == MT6370_FLED2) { pr_err("%s not support set strobe timeout\n", __func__); return -EINVAL; } ret = mt6370_pmu_reg_update_bits(fi->chip, fi->fled_strb_to_reg, MT6370_FLED_STROBE_TIMEOUT_MASK, selector << MT6370_FLED_STROBE_TIMEOUT_SHIFT); return ret; } static int mt6370_fled_get_torch_current_sel(struct rt_fled_dev *info) { struct mt6370_pmu_fled_data *fi = (struct mt6370_pmu_fled_data *)info; int ret = 0; ret = mt6370_pmu_reg_read(fi->chip, fi->fled_tor_cur_reg); if (ret < 0) { pr_err("%s get fled tor current sel fail\n", __func__); return ret; } ret &= MT6370_FLED_TORCHCUR_MASK; ret >>= MT6370_FLED_TORCHCUR_SHIFT; return ret; } static int mt6370_fled_get_strobe_current_sel(struct rt_fled_dev *info) { struct mt6370_pmu_fled_data *fi = (struct mt6370_pmu_fled_data *)info; int ret = 0; ret = mt6370_pmu_reg_read(fi->chip, fi->fled_strb_cur_reg); if (ret < 0) { pr_err("%s get fled strobe curr sel fail\n", __func__); return ret; } ret &= MT6370_FLED_STROBECUR_MASK; ret >>= MT6370_FLED_STROBECUR_SHIFT; return ret; } static int mt6370_fled_get_timeout_level_sel(struct rt_fled_dev *info) { struct mt6370_pmu_fled_data *fi = (struct mt6370_pmu_fled_data *)info; int ret = 0; if (fi->id == MT6370_FLED1) ret = mt6370_pmu_reg_read(fi->chip, MT6370_PMU_REG_FLED1CTRL); else ret = mt6370_pmu_reg_read(fi->chip, MT6370_PMU_REG_FLED2CTRL); if (ret < 0) { pr_err("%s get fled timeout level fail\n", __func__); return ret; } ret &= MT6370_FLED_TIMEOUT_LEVEL_MASK; ret >>= MT6370_TIMEOUT_LEVEL_SHIFT; return ret; } static int mt6370_fled_get_strobe_timeout_sel(struct rt_fled_dev *info) { struct mt6370_pmu_fled_data *fi = (struct mt6370_pmu_fled_data *)info; int ret = 0; ret = mt6370_pmu_reg_read(fi->chip, fi->fled_strb_to_reg); if (ret < 0) { pr_err("%s get fled timeout level fail\n", __func__); return ret; } ret &= MT6370_FLED_STROBE_TIMEOUT_MASK; ret >>= MT6370_FLED_STROBE_TIMEOUT_SHIFT; return ret; } static void mt6370_fled_shutdown(struct rt_fled_dev *info) { mt6370_fled_set_mode(info, FLASHLIGHT_MODE_OFF); } static int mt6370_fled_is_ready(struct rt_fled_dev *info) { struct mt6370_pmu_fled_data *fi = (struct mt6370_pmu_fled_data *)info; int ret; ret = mt6370_pmu_reg_read(fi->chip, MT6370_PMU_REG_CHGSTAT2); if (ret < 0) { pr_err("%s read flash ready bit fail\n", __func__); return 0; } /* CHG_STAT2 bit[3] CHG_VINOVP, * if OVP = 0 --> V < 5.3, if OVP = 1, V > 5.6 */ return ret & 0x08 ? 0 : 1; } static struct rt_fled_hal mt6370_fled_hal = { .rt_hal_fled_init = mt6370_fled_init, .rt_hal_fled_suspend = mt6370_fled_suspend, .rt_hal_fled_resume = mt6370_fled_resume, .rt_hal_fled_set_mode = mt6370_fled_set_mode, .rt_hal_fled_get_mode = mt6370_fled_get_mode, .rt_hal_fled_strobe = mt6370_fled_strobe, .rt_hal_fled_get_is_ready = mt6370_fled_is_ready, .rt_hal_fled_torch_current_list = mt6370_fled_torch_current_list, .rt_hal_fled_strobe_current_list = mt6370_fled_strobe_current_list, .rt_hal_fled_timeout_level_list = mt6370_fled_timeout_level_list, /* .fled_lv_protection_list = mt6370_fled_lv_protection_list, */ .rt_hal_fled_strobe_timeout_list = mt6370_fled_strobe_timeout_list, /* method to set */ .rt_hal_fled_set_torch_current_sel = mt6370_fled_set_torch_current_sel, .rt_hal_fled_set_strobe_current_sel = mt6370_fled_set_strobe_current_sel, .rt_hal_fled_set_timeout_level_sel = mt6370_fled_set_timeout_level_sel, .rt_hal_fled_set_strobe_timeout_sel = mt6370_fled_set_strobe_timeout_sel, /* method to get */ .rt_hal_fled_get_torch_current_sel = mt6370_fled_get_torch_current_sel, .rt_hal_fled_get_strobe_current_sel = mt6370_fled_get_strobe_current_sel, .rt_hal_fled_get_timeout_level_sel = mt6370_fled_get_timeout_level_sel, .rt_hal_fled_get_strobe_timeout_sel = mt6370_fled_get_strobe_timeout_sel, /* PM shutdown, optional */ .rt_hal_fled_shutdown = mt6370_fled_shutdown, }; #define MT6370_FLED_TOR_CUR0 MT6370_PMU_REG_FLED1TORCTRL #define MT6370_FLED_TOR_CUR1 MT6370_PMU_REG_FLED2TORCTRL #define MT6370_FLED_STRB_CUR0 MT6370_PMU_REG_FLED1STRBCTRL #define MT6370_FLED_STRB_CUR1 MT6370_PMU_REG_FLED2STRBCTRL2 #define MT6370_FLED_CS_MASK0 0x02 #define MT6370_FLED_CS_MASK1 0x01 #define MT6370_FLED_DEVICE(_id) \ { \ .id = _id, \ .fled_ctrl_reg = MT6370_PMU_REG_FLEDEN, \ .fled_tor_cur_reg = MT6370_FLED_TOR_CUR##_id, \ .fled_strb_cur_reg = MT6370_FLED_STRB_CUR##_id, \ .fled_strb_to_reg = MT6370_PMU_REG_FLEDSTRBCTRL, \ .fled_cs_mask = MT6370_FLED_CS_MASK##_id, \ } static struct mt6370_pmu_fled_data mt6370_pmu_fleds[] = { MT6370_FLED_DEVICE(0), MT6370_FLED_DEVICE(1), }; static struct mt6370_pmu_fled_data *mt6370_find_info(int id) { struct mt6370_pmu_fled_data *fi; unsigned int i; for (i = 0; i < ARRAY_SIZE(mt6370_pmu_fleds); i++) { fi = &mt6370_pmu_fleds[i]; if (fi->id == id) return fi; } return NULL; } static int mt6370_pmu_fled_probe(struct platform_device *pdev) { struct mt6370_pmu_fled_data *fled_data; bool use_dt = pdev->dev.of_node; int ret; pr_info("%s: (%s) id = %d\n", __func__, MT6370_PMU_FLED_DRV_VERSION, pdev->id); fled_data = mt6370_find_info(pdev->id); if (fled_data == NULL) { dev_err(&pdev->dev, "invalid fled ID Specified\n"); return -EINVAL; } fled_data->chip = dev_get_drvdata(pdev->dev.parent); fled_data->dev = &pdev->dev; if (use_dt) mt6370_fled_parse_dt(&pdev->dev, fled_data); platform_set_drvdata(pdev, fled_data); fled_data->base.init_props = &mt6370_fled_props; fled_data->base.hal = &mt6370_fled_hal; if (pdev->id == 0) fled_data->base.name = "mt-flash-led1"; else fled_data->base.name = "mt-flash-led2"; fled_data->base.chip_name = "mt6370_pmu_fled"; pr_info("%s flash name = %s\n", __func__, fled_data->base.name); fled_data->mt_flash_dev = platform_device_register_resndata( fled_data->dev, "rt-flash-led", fled_data->id, NULL, 0, NULL, 0); if (!mt6370_fled_inited) { ret = mt6370_pmu_reg_clr_bit(fled_data->chip, MT6370_PMU_REG_FLEDVMIDTRKCTRL1, MT6370_FLED_FIXED_MODE_MASK); if (ret < 0) { pr_err("%s set fled fixed mode fail\n", __func__); return -EINVAL; } mt6370_pmu_fled_irq_register(pdev); mt6370_fled_inited = 1; dev_info(&pdev->dev, "mt6370 fled inited\n"); } dev_info(&pdev->dev, "%s successfully\n", __func__); return 0; } static int mt6370_pmu_fled_remove(struct platform_device *pdev) { struct mt6370_pmu_fled_data *fled_data = platform_get_drvdata(pdev); platform_device_unregister(fled_data->mt_flash_dev); dev_info(fled_data->dev, "%s successfully\n", __func__); return 0; } static const struct of_device_id mt_ofid_table[] = { { .compatible = "mediatek,mt6370_pmu_fled1", }, { .compatible = "mediatek,mt6370_pmu_fled2", }, { }, }; MODULE_DEVICE_TABLE(of, mt_ofid_table); #if 0 static const struct platform_device_id mt_id_table[] = { { "mt6370_pmu_fled1", 0}, { "mt6370_pmu_fled2", 0}, { }, }; MODULE_DEVICE_TABLE(platform, mt_id_table); #endif static struct platform_driver mt6370_pmu_fled = { .driver = { .name = "mt6370_pmu_fled", .owner = THIS_MODULE, .of_match_table = of_match_ptr(mt_ofid_table), }, .probe = mt6370_pmu_fled_probe, .remove = mt6370_pmu_fled_remove, /*.id_table = mt_id_table, */ }; module_platform_driver(mt6370_pmu_fled); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("MediaTek MT6370 PMU Fled"); MODULE_VERSION(MT6370_PMU_FLED_DRV_VERSION); /* * Release Note * 1.0.3_MTK * (1) Print warnings when strobe mode with HZ=1 or CFO=0 * * 1.0.2_MTK * (1) Add delay for strobe on/off * * 1.0.1_MTK * (1) Remove typedef * * 1.0.0_MTK * (1) Initial Release */