2019-05-27 09:55:21 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2015-02-22 15:15:29 +03:00
/*
* Copyright ( c ) 2014 MediaTek Inc .
* Author : Flora Fu , MediaTek
*/
# include <linux/interrupt.h>
2019-08-18 16:56:06 +03:00
# include <linux/ioport.h>
2015-02-22 15:15:29 +03:00
# include <linux/module.h>
# include <linux/of_device.h>
# include <linux/of_irq.h>
# include <linux/regmap.h>
# include <linux/mfd/core.h>
2016-01-27 14:47:38 +03:00
# include <linux/mfd/mt6323/core.h>
2020-04-21 06:00:10 +03:00
# include <linux/mfd/mt6358/core.h>
2021-05-26 09:52:04 +03:00
# include <linux/mfd/mt6359/core.h>
2019-08-05 08:21:49 +03:00
# include <linux/mfd/mt6397/core.h>
2016-01-27 14:47:38 +03:00
# include <linux/mfd/mt6323/registers.h>
2020-04-21 06:00:10 +03:00
# include <linux/mfd/mt6358/registers.h>
2021-05-26 09:52:04 +03:00
# include <linux/mfd/mt6359/registers.h>
2019-08-05 08:21:49 +03:00
# include <linux/mfd/mt6397/registers.h>
2015-02-22 15:15:29 +03:00
2019-08-18 16:56:08 +03:00
# define MT6323_RTC_BASE 0x8000
# define MT6323_RTC_SIZE 0x40
2020-04-21 06:00:10 +03:00
# define MT6358_RTC_BASE 0x0588
# define MT6358_RTC_SIZE 0x3c
2015-05-06 10:23:40 +03:00
# define MT6397_RTC_BASE 0xe000
# define MT6397_RTC_SIZE 0x3e
2019-08-18 16:56:08 +03:00
# define MT6323_PWRC_BASE 0x8000
# define MT6323_PWRC_SIZE 0x40
static const struct resource mt6323_rtc_resources [ ] = {
DEFINE_RES_MEM ( MT6323_RTC_BASE , MT6323_RTC_SIZE ) ,
DEFINE_RES_IRQ ( MT6323_IRQ_STATUS_RTC ) ,
} ;
2020-04-21 06:00:10 +03:00
static const struct resource mt6358_rtc_resources [ ] = {
DEFINE_RES_MEM ( MT6358_RTC_BASE , MT6358_RTC_SIZE ) ,
DEFINE_RES_IRQ ( MT6358_IRQ_RTC ) ,
} ;
2015-05-06 10:23:40 +03:00
static const struct resource mt6397_rtc_resources [ ] = {
2019-08-18 16:56:06 +03:00
DEFINE_RES_MEM ( MT6397_RTC_BASE , MT6397_RTC_SIZE ) ,
DEFINE_RES_IRQ ( MT6397_IRQ_RTC ) ,
2015-05-06 10:23:40 +03:00
} ;
2021-05-06 12:41:15 +03:00
static const struct resource mt6358_keys_resources [ ] = {
DEFINE_RES_IRQ_NAMED ( MT6358_IRQ_PWRKEY , " powerkey " ) ,
DEFINE_RES_IRQ_NAMED ( MT6358_IRQ_HOMEKEY , " homekey " ) ,
DEFINE_RES_IRQ_NAMED ( MT6358_IRQ_PWRKEY_R , " powerkey_r " ) ,
DEFINE_RES_IRQ_NAMED ( MT6358_IRQ_HOMEKEY_R , " homekey_r " ) ,
} ;
2017-10-25 16:16:04 +03:00
static const struct resource mt6323_keys_resources [ ] = {
2021-05-06 12:41:14 +03:00
DEFINE_RES_IRQ_NAMED ( MT6323_IRQ_STATUS_PWRKEY , " powerkey " ) ,
DEFINE_RES_IRQ_NAMED ( MT6323_IRQ_STATUS_FCHRKEY , " homekey " ) ,
2017-10-25 16:16:04 +03:00
} ;
static const struct resource mt6397_keys_resources [ ] = {
2021-05-06 12:41:14 +03:00
DEFINE_RES_IRQ_NAMED ( MT6397_IRQ_PWRKEY , " powerkey " ) ,
DEFINE_RES_IRQ_NAMED ( MT6397_IRQ_HOMEKEY , " homekey " ) ,
2017-10-25 16:16:04 +03:00
} ;
2019-08-18 16:56:08 +03:00
static const struct resource mt6323_pwrc_resources [ ] = {
DEFINE_RES_MEM ( MT6323_PWRC_BASE , MT6323_PWRC_SIZE ) ,
} ;
2016-01-27 14:47:38 +03:00
static const struct mfd_cell mt6323_devs [ ] = {
{
2019-08-18 16:56:08 +03:00
. name = " mt6323-rtc " ,
. num_resources = ARRAY_SIZE ( mt6323_rtc_resources ) ,
. resources = mt6323_rtc_resources ,
. of_compatible = " mediatek,mt6323-rtc " ,
} , {
2016-01-27 14:47:38 +03:00
. name = " mt6323-regulator " ,
. of_compatible = " mediatek,mt6323-regulator "
2017-03-20 09:47:27 +03:00
} , {
2017-01-23 06:54:45 +03:00
. name = " mt6323-led " ,
. of_compatible = " mediatek,mt6323-led "
2017-10-25 16:16:04 +03:00
} , {
. name = " mtk-pmic-keys " ,
. num_resources = ARRAY_SIZE ( mt6323_keys_resources ) ,
. resources = mt6323_keys_resources ,
. of_compatible = " mediatek,mt6323-keys "
2019-08-18 16:56:08 +03:00
} , {
. name = " mt6323-pwrc " ,
. num_resources = ARRAY_SIZE ( mt6323_pwrc_resources ) ,
. resources = mt6323_pwrc_resources ,
. of_compatible = " mediatek,mt6323-pwrc "
2017-01-23 06:54:45 +03:00
} ,
2016-01-27 14:47:38 +03:00
} ;
2020-04-21 06:00:10 +03:00
static const struct mfd_cell mt6358_devs [ ] = {
{
. name = " mt6358-regulator " ,
. of_compatible = " mediatek,mt6358-regulator "
} , {
. name = " mt6358-rtc " ,
. num_resources = ARRAY_SIZE ( mt6358_rtc_resources ) ,
. resources = mt6358_rtc_resources ,
. of_compatible = " mediatek,mt6358-rtc " ,
} , {
. name = " mt6358-sound " ,
. of_compatible = " mediatek,mt6358-sound "
2021-05-06 12:41:15 +03:00
} , {
. name = " mt6358-keys " ,
. num_resources = ARRAY_SIZE ( mt6358_keys_resources ) ,
. resources = mt6358_keys_resources ,
. of_compatible = " mediatek,mt6358-keys "
2020-04-21 06:00:10 +03:00
} ,
} ;
2021-05-26 09:52:04 +03:00
static const struct mfd_cell mt6359_devs [ ] = {
{ . name = " mt6359-regulator " , } ,
{
. name = " mt6359-rtc " ,
. num_resources = ARRAY_SIZE ( mt6358_rtc_resources ) ,
. resources = mt6358_rtc_resources ,
. of_compatible = " mediatek,mt6358-rtc " ,
} ,
{ . name = " mt6359-sound " , } ,
} ;
2015-02-22 15:15:29 +03:00
static const struct mfd_cell mt6397_devs [ ] = {
{
. name = " mt6397-rtc " ,
2015-05-06 10:23:40 +03:00
. num_resources = ARRAY_SIZE ( mt6397_rtc_resources ) ,
. resources = mt6397_rtc_resources ,
2015-02-22 15:15:29 +03:00
. of_compatible = " mediatek,mt6397-rtc " ,
} , {
. name = " mt6397-regulator " ,
. of_compatible = " mediatek,mt6397-regulator " ,
} , {
. name = " mt6397-codec " ,
. of_compatible = " mediatek,mt6397-codec " ,
} , {
. name = " mt6397-clk " ,
. of_compatible = " mediatek,mt6397-clk " ,
2015-05-27 12:10:35 +03:00
} , {
. name = " mt6397-pinctrl " ,
. of_compatible = " mediatek,mt6397-pinctrl " ,
2017-10-25 16:16:04 +03:00
} , {
. name = " mtk-pmic-keys " ,
. num_resources = ARRAY_SIZE ( mt6397_keys_resources ) ,
. resources = mt6397_keys_resources ,
. of_compatible = " mediatek,mt6397-keys "
}
2015-02-22 15:15:29 +03:00
} ;
2019-10-03 21:53:23 +03:00
struct chip_data {
u32 cid_addr ;
u32 cid_shift ;
2020-04-21 06:00:08 +03:00
const struct mfd_cell * cells ;
int cell_size ;
int ( * irq_init ) ( struct mt6397_chip * chip ) ;
2019-10-03 21:53:23 +03:00
} ;
static const struct chip_data mt6323_core = {
. cid_addr = MT6323_CID ,
. cid_shift = 0 ,
2020-04-21 06:00:08 +03:00
. cells = mt6323_devs ,
. cell_size = ARRAY_SIZE ( mt6323_devs ) ,
. irq_init = mt6397_irq_init ,
2019-10-03 21:53:23 +03:00
} ;
2020-04-21 06:00:10 +03:00
static const struct chip_data mt6358_core = {
. cid_addr = MT6358_SWCID ,
. cid_shift = 8 ,
. cells = mt6358_devs ,
. cell_size = ARRAY_SIZE ( mt6358_devs ) ,
. irq_init = mt6358_irq_init ,
} ;
2021-05-26 09:52:04 +03:00
static const struct chip_data mt6359_core = {
. cid_addr = MT6359_SWCID ,
. cid_shift = 8 ,
. cells = mt6359_devs ,
. cell_size = ARRAY_SIZE ( mt6359_devs ) ,
. irq_init = mt6358_irq_init ,
} ;
2019-10-03 21:53:23 +03:00
static const struct chip_data mt6397_core = {
. cid_addr = MT6397_CID ,
. cid_shift = 0 ,
2020-04-21 06:00:08 +03:00
. cells = mt6397_devs ,
. cell_size = ARRAY_SIZE ( mt6397_devs ) ,
. irq_init = mt6397_irq_init ,
2019-10-03 21:53:23 +03:00
} ;
2015-02-22 15:15:29 +03:00
static int mt6397_probe ( struct platform_device * pdev )
{
int ret ;
2020-04-21 06:00:08 +03:00
unsigned int id = 0 ;
2016-01-27 14:47:37 +03:00
struct mt6397_chip * pmic ;
2019-10-03 21:53:23 +03:00
const struct chip_data * pmic_core ;
2015-02-22 15:15:29 +03:00
2016-01-27 14:47:37 +03:00
pmic = devm_kzalloc ( & pdev - > dev , sizeof ( * pmic ) , GFP_KERNEL ) ;
if ( ! pmic )
2015-02-22 15:15:29 +03:00
return - ENOMEM ;
2016-01-27 14:47:37 +03:00
pmic - > dev = & pdev - > dev ;
2016-01-27 14:47:36 +03:00
2015-02-22 15:15:29 +03:00
/*
* mt6397 MFD is child device of soc pmic wrapper .
* Regmap is set from its parent .
*/
2016-01-27 14:47:37 +03:00
pmic - > regmap = dev_get_regmap ( pdev - > dev . parent , NULL ) ;
if ( ! pmic - > regmap )
2015-02-22 15:15:29 +03:00
return - ENODEV ;
2019-10-03 21:53:23 +03:00
pmic_core = of_device_get_match_data ( & pdev - > dev ) ;
if ( ! pmic_core )
return - ENODEV ;
2016-01-27 14:47:37 +03:00
2019-10-03 21:53:23 +03:00
ret = regmap_read ( pmic - > regmap , pmic_core - > cid_addr , & id ) ;
2016-01-27 14:47:37 +03:00
if ( ret ) {
2019-10-03 21:53:23 +03:00
dev_err ( & pdev - > dev , " Failed to read chip id: %d \n " , ret ) ;
2016-04-15 11:30:29 +03:00
return ret ;
2016-01-27 14:47:37 +03:00
}
2019-10-03 21:53:23 +03:00
pmic - > chip_id = ( id > > pmic_core - > cid_shift ) & 0xff ;
platform_set_drvdata ( pdev , pmic ) ;
2016-04-15 11:30:29 +03:00
pmic - > irq = platform_get_irq ( pdev , 0 ) ;
if ( pmic - > irq < = 0 )
return pmic - > irq ;
2020-04-21 06:00:08 +03:00
ret = pmic_core - > irq_init ( pmic ) ;
2019-10-03 21:53:23 +03:00
if ( ret )
return ret ;
2016-04-15 11:30:29 +03:00
2020-04-21 06:00:08 +03:00
ret = devm_mfd_add_devices ( & pdev - > dev , PLATFORM_DEVID_NONE ,
pmic_core - > cells , pmic_core - > cell_size ,
NULL , 0 , pmic - > irq_domain ) ;
2016-01-27 14:47:37 +03:00
if ( ret ) {
irq_domain_remove ( pmic - > irq_domain ) ;
2015-02-22 15:15:29 +03:00
dev_err ( & pdev - > dev , " failed to add child devices: %d \n " , ret ) ;
2016-01-27 14:47:37 +03:00
}
2015-02-22 15:15:29 +03:00
return ret ;
}
static const struct of_device_id mt6397_of_match [ ] = {
2019-10-03 21:53:23 +03:00
{
. compatible = " mediatek,mt6323 " ,
. data = & mt6323_core ,
2020-04-21 06:00:10 +03:00
} , {
. compatible = " mediatek,mt6358 " ,
. data = & mt6358_core ,
2021-05-26 09:52:04 +03:00
} , {
. compatible = " mediatek,mt6359 " ,
. data = & mt6359_core ,
2019-10-03 21:53:23 +03:00
} , {
. compatible = " mediatek,mt6397 " ,
. data = & mt6397_core ,
} , {
/* sentinel */
}
2015-02-22 15:15:29 +03:00
} ;
MODULE_DEVICE_TABLE ( of , mt6397_of_match ) ;
2016-02-10 19:50:18 +03:00
static const struct platform_device_id mt6397_id [ ] = {
{ " mt6397 " , 0 } ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( platform , mt6397_id ) ;
2015-02-22 15:15:29 +03:00
static struct platform_driver mt6397_driver = {
. probe = mt6397_probe ,
. driver = {
. name = " mt6397 " ,
2020-11-20 19:21:27 +03:00
. of_match_table = mt6397_of_match ,
2015-02-22 15:15:29 +03:00
} ,
2016-02-10 19:50:18 +03:00
. id_table = mt6397_id ,
2015-02-22 15:15:29 +03:00
} ;
module_platform_driver ( mt6397_driver ) ;
MODULE_AUTHOR ( " Flora Fu, MediaTek " ) ;
MODULE_DESCRIPTION ( " Driver for MediaTek MT6397 PMIC " ) ;
MODULE_LICENSE ( " GPL " ) ;