cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

rtc-hym8563.c (13944B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Haoyu HYM8563 RTC driver
      4 *
      5 * Copyright (C) 2013 MundoReader S.L.
      6 * Author: Heiko Stuebner <heiko@sntech.de>
      7 *
      8 * based on rtc-HYM8563
      9 * Copyright (C) 2010 ROCKCHIP, Inc.
     10 */
     11
     12#include <linux/module.h>
     13#include <linux/clk-provider.h>
     14#include <linux/i2c.h>
     15#include <linux/bcd.h>
     16#include <linux/rtc.h>
     17
     18#define HYM8563_CTL1		0x00
     19#define HYM8563_CTL1_TEST	BIT(7)
     20#define HYM8563_CTL1_STOP	BIT(5)
     21#define HYM8563_CTL1_TESTC	BIT(3)
     22
     23#define HYM8563_CTL2		0x01
     24#define HYM8563_CTL2_TI_TP	BIT(4)
     25#define HYM8563_CTL2_AF		BIT(3)
     26#define HYM8563_CTL2_TF		BIT(2)
     27#define HYM8563_CTL2_AIE	BIT(1)
     28#define HYM8563_CTL2_TIE	BIT(0)
     29
     30#define HYM8563_SEC		0x02
     31#define HYM8563_SEC_VL		BIT(7)
     32#define HYM8563_SEC_MASK	0x7f
     33
     34#define HYM8563_MIN		0x03
     35#define HYM8563_MIN_MASK	0x7f
     36
     37#define HYM8563_HOUR		0x04
     38#define HYM8563_HOUR_MASK	0x3f
     39
     40#define HYM8563_DAY		0x05
     41#define HYM8563_DAY_MASK	0x3f
     42
     43#define HYM8563_WEEKDAY		0x06
     44#define HYM8563_WEEKDAY_MASK	0x07
     45
     46#define HYM8563_MONTH		0x07
     47#define HYM8563_MONTH_CENTURY	BIT(7)
     48#define HYM8563_MONTH_MASK	0x1f
     49
     50#define HYM8563_YEAR		0x08
     51
     52#define HYM8563_ALM_MIN		0x09
     53#define HYM8563_ALM_HOUR	0x0a
     54#define HYM8563_ALM_DAY		0x0b
     55#define HYM8563_ALM_WEEK	0x0c
     56
     57/* Each alarm check can be disabled by setting this bit in the register */
     58#define HYM8563_ALM_BIT_DISABLE	BIT(7)
     59
     60#define HYM8563_CLKOUT		0x0d
     61#define HYM8563_CLKOUT_ENABLE	BIT(7)
     62#define HYM8563_CLKOUT_32768	0
     63#define HYM8563_CLKOUT_1024	1
     64#define HYM8563_CLKOUT_32	2
     65#define HYM8563_CLKOUT_1	3
     66#define HYM8563_CLKOUT_MASK	3
     67
     68#define HYM8563_TMR_CTL		0x0e
     69#define HYM8563_TMR_CTL_ENABLE	BIT(7)
     70#define HYM8563_TMR_CTL_4096	0
     71#define HYM8563_TMR_CTL_64	1
     72#define HYM8563_TMR_CTL_1	2
     73#define HYM8563_TMR_CTL_1_60	3
     74#define HYM8563_TMR_CTL_MASK	3
     75
     76#define HYM8563_TMR_CNT		0x0f
     77
     78struct hym8563 {
     79	struct i2c_client	*client;
     80	struct rtc_device	*rtc;
     81#ifdef CONFIG_COMMON_CLK
     82	struct clk_hw		clkout_hw;
     83#endif
     84};
     85
     86/*
     87 * RTC handling
     88 */
     89
     90static int hym8563_rtc_read_time(struct device *dev, struct rtc_time *tm)
     91{
     92	struct i2c_client *client = to_i2c_client(dev);
     93	u8 buf[7];
     94	int ret;
     95
     96	ret = i2c_smbus_read_i2c_block_data(client, HYM8563_SEC, 7, buf);
     97	if (ret < 0)
     98		return ret;
     99
    100	if (buf[0] & HYM8563_SEC_VL) {
    101		dev_warn(&client->dev,
    102			 "no valid clock/calendar values available\n");
    103		return -EINVAL;
    104	}
    105
    106	tm->tm_sec = bcd2bin(buf[0] & HYM8563_SEC_MASK);
    107	tm->tm_min = bcd2bin(buf[1] & HYM8563_MIN_MASK);
    108	tm->tm_hour = bcd2bin(buf[2] & HYM8563_HOUR_MASK);
    109	tm->tm_mday = bcd2bin(buf[3] & HYM8563_DAY_MASK);
    110	tm->tm_wday = bcd2bin(buf[4] & HYM8563_WEEKDAY_MASK); /* 0 = Sun */
    111	tm->tm_mon = bcd2bin(buf[5] & HYM8563_MONTH_MASK) - 1; /* 0 = Jan */
    112	tm->tm_year = bcd2bin(buf[6]) + 100;
    113
    114	return 0;
    115}
    116
    117static int hym8563_rtc_set_time(struct device *dev, struct rtc_time *tm)
    118{
    119	struct i2c_client *client = to_i2c_client(dev);
    120	u8 buf[7];
    121	int ret;
    122
    123	/* Years >= 2100 are to far in the future, 19XX is to early */
    124	if (tm->tm_year < 100 || tm->tm_year >= 200)
    125		return -EINVAL;
    126
    127	buf[0] = bin2bcd(tm->tm_sec);
    128	buf[1] = bin2bcd(tm->tm_min);
    129	buf[2] = bin2bcd(tm->tm_hour);
    130	buf[3] = bin2bcd(tm->tm_mday);
    131	buf[4] = bin2bcd(tm->tm_wday);
    132	buf[5] = bin2bcd(tm->tm_mon + 1);
    133
    134	/*
    135	 * While the HYM8563 has a century flag in the month register,
    136	 * it does not seem to carry it over a subsequent write/read.
    137	 * So we'll limit ourself to 100 years, starting at 2000 for now.
    138	 */
    139	buf[6] = bin2bcd(tm->tm_year - 100);
    140
    141	/*
    142	 * CTL1 only contains TEST-mode bits apart from stop,
    143	 * so no need to read the value first
    144	 */
    145	ret = i2c_smbus_write_byte_data(client, HYM8563_CTL1,
    146						HYM8563_CTL1_STOP);
    147	if (ret < 0)
    148		return ret;
    149
    150	ret = i2c_smbus_write_i2c_block_data(client, HYM8563_SEC, 7, buf);
    151	if (ret < 0)
    152		return ret;
    153
    154	ret = i2c_smbus_write_byte_data(client, HYM8563_CTL1, 0);
    155	if (ret < 0)
    156		return ret;
    157
    158	return 0;
    159}
    160
    161static int hym8563_rtc_alarm_irq_enable(struct device *dev,
    162					unsigned int enabled)
    163{
    164	struct i2c_client *client = to_i2c_client(dev);
    165	int data;
    166
    167	data = i2c_smbus_read_byte_data(client, HYM8563_CTL2);
    168	if (data < 0)
    169		return data;
    170
    171	if (enabled)
    172		data |= HYM8563_CTL2_AIE;
    173	else
    174		data &= ~HYM8563_CTL2_AIE;
    175
    176	return i2c_smbus_write_byte_data(client, HYM8563_CTL2, data);
    177};
    178
    179static int hym8563_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
    180{
    181	struct i2c_client *client = to_i2c_client(dev);
    182	struct rtc_time *alm_tm = &alm->time;
    183	u8 buf[4];
    184	int ret;
    185
    186	ret = i2c_smbus_read_i2c_block_data(client, HYM8563_ALM_MIN, 4, buf);
    187	if (ret < 0)
    188		return ret;
    189
    190	/* The alarm only has a minute accuracy */
    191	alm_tm->tm_sec = 0;
    192
    193	alm_tm->tm_min = (buf[0] & HYM8563_ALM_BIT_DISABLE) ?
    194					-1 :
    195					bcd2bin(buf[0] & HYM8563_MIN_MASK);
    196	alm_tm->tm_hour = (buf[1] & HYM8563_ALM_BIT_DISABLE) ?
    197					-1 :
    198					bcd2bin(buf[1] & HYM8563_HOUR_MASK);
    199	alm_tm->tm_mday = (buf[2] & HYM8563_ALM_BIT_DISABLE) ?
    200					-1 :
    201					bcd2bin(buf[2] & HYM8563_DAY_MASK);
    202	alm_tm->tm_wday = (buf[3] & HYM8563_ALM_BIT_DISABLE) ?
    203					-1 :
    204					bcd2bin(buf[3] & HYM8563_WEEKDAY_MASK);
    205
    206	ret = i2c_smbus_read_byte_data(client, HYM8563_CTL2);
    207	if (ret < 0)
    208		return ret;
    209
    210	if (ret & HYM8563_CTL2_AIE)
    211		alm->enabled = 1;
    212
    213	return 0;
    214}
    215
    216static int hym8563_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
    217{
    218	struct i2c_client *client = to_i2c_client(dev);
    219	struct rtc_time *alm_tm = &alm->time;
    220	u8 buf[4];
    221	int ret;
    222
    223	ret = i2c_smbus_read_byte_data(client, HYM8563_CTL2);
    224	if (ret < 0)
    225		return ret;
    226
    227	ret &= ~HYM8563_CTL2_AIE;
    228
    229	ret = i2c_smbus_write_byte_data(client, HYM8563_CTL2, ret);
    230	if (ret < 0)
    231		return ret;
    232
    233	buf[0] = (alm_tm->tm_min < 60 && alm_tm->tm_min >= 0) ?
    234			bin2bcd(alm_tm->tm_min) : HYM8563_ALM_BIT_DISABLE;
    235
    236	buf[1] = (alm_tm->tm_hour < 24 && alm_tm->tm_hour >= 0) ?
    237			bin2bcd(alm_tm->tm_hour) : HYM8563_ALM_BIT_DISABLE;
    238
    239	buf[2] = (alm_tm->tm_mday <= 31 && alm_tm->tm_mday >= 1) ?
    240			bin2bcd(alm_tm->tm_mday) : HYM8563_ALM_BIT_DISABLE;
    241
    242	buf[3] = (alm_tm->tm_wday < 7 && alm_tm->tm_wday >= 0) ?
    243			bin2bcd(alm_tm->tm_wday) : HYM8563_ALM_BIT_DISABLE;
    244
    245	ret = i2c_smbus_write_i2c_block_data(client, HYM8563_ALM_MIN, 4, buf);
    246	if (ret < 0)
    247		return ret;
    248
    249	return hym8563_rtc_alarm_irq_enable(dev, alm->enabled);
    250}
    251
    252static const struct rtc_class_ops hym8563_rtc_ops = {
    253	.read_time		= hym8563_rtc_read_time,
    254	.set_time		= hym8563_rtc_set_time,
    255	.alarm_irq_enable	= hym8563_rtc_alarm_irq_enable,
    256	.read_alarm		= hym8563_rtc_read_alarm,
    257	.set_alarm		= hym8563_rtc_set_alarm,
    258};
    259
    260/*
    261 * Handling of the clkout
    262 */
    263
    264#ifdef CONFIG_COMMON_CLK
    265#define clkout_hw_to_hym8563(_hw) container_of(_hw, struct hym8563, clkout_hw)
    266
    267static int clkout_rates[] = {
    268	32768,
    269	1024,
    270	32,
    271	1,
    272};
    273
    274static unsigned long hym8563_clkout_recalc_rate(struct clk_hw *hw,
    275						unsigned long parent_rate)
    276{
    277	struct hym8563 *hym8563 = clkout_hw_to_hym8563(hw);
    278	struct i2c_client *client = hym8563->client;
    279	int ret = i2c_smbus_read_byte_data(client, HYM8563_CLKOUT);
    280
    281	if (ret < 0)
    282		return 0;
    283
    284	ret &= HYM8563_CLKOUT_MASK;
    285	return clkout_rates[ret];
    286}
    287
    288static long hym8563_clkout_round_rate(struct clk_hw *hw, unsigned long rate,
    289				      unsigned long *prate)
    290{
    291	int i;
    292
    293	for (i = 0; i < ARRAY_SIZE(clkout_rates); i++)
    294		if (clkout_rates[i] <= rate)
    295			return clkout_rates[i];
    296
    297	return 0;
    298}
    299
    300static int hym8563_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
    301				   unsigned long parent_rate)
    302{
    303	struct hym8563 *hym8563 = clkout_hw_to_hym8563(hw);
    304	struct i2c_client *client = hym8563->client;
    305	int ret = i2c_smbus_read_byte_data(client, HYM8563_CLKOUT);
    306	int i;
    307
    308	if (ret < 0)
    309		return ret;
    310
    311	for (i = 0; i < ARRAY_SIZE(clkout_rates); i++)
    312		if (clkout_rates[i] == rate) {
    313			ret &= ~HYM8563_CLKOUT_MASK;
    314			ret |= i;
    315			return i2c_smbus_write_byte_data(client,
    316							 HYM8563_CLKOUT, ret);
    317		}
    318
    319	return -EINVAL;
    320}
    321
    322static int hym8563_clkout_control(struct clk_hw *hw, bool enable)
    323{
    324	struct hym8563 *hym8563 = clkout_hw_to_hym8563(hw);
    325	struct i2c_client *client = hym8563->client;
    326	int ret = i2c_smbus_read_byte_data(client, HYM8563_CLKOUT);
    327
    328	if (ret < 0)
    329		return ret;
    330
    331	if (enable)
    332		ret |= HYM8563_CLKOUT_ENABLE;
    333	else
    334		ret &= ~HYM8563_CLKOUT_ENABLE;
    335
    336	return i2c_smbus_write_byte_data(client, HYM8563_CLKOUT, ret);
    337}
    338
    339static int hym8563_clkout_prepare(struct clk_hw *hw)
    340{
    341	return hym8563_clkout_control(hw, 1);
    342}
    343
    344static void hym8563_clkout_unprepare(struct clk_hw *hw)
    345{
    346	hym8563_clkout_control(hw, 0);
    347}
    348
    349static int hym8563_clkout_is_prepared(struct clk_hw *hw)
    350{
    351	struct hym8563 *hym8563 = clkout_hw_to_hym8563(hw);
    352	struct i2c_client *client = hym8563->client;
    353	int ret = i2c_smbus_read_byte_data(client, HYM8563_CLKOUT);
    354
    355	if (ret < 0)
    356		return ret;
    357
    358	return !!(ret & HYM8563_CLKOUT_ENABLE);
    359}
    360
    361static const struct clk_ops hym8563_clkout_ops = {
    362	.prepare = hym8563_clkout_prepare,
    363	.unprepare = hym8563_clkout_unprepare,
    364	.is_prepared = hym8563_clkout_is_prepared,
    365	.recalc_rate = hym8563_clkout_recalc_rate,
    366	.round_rate = hym8563_clkout_round_rate,
    367	.set_rate = hym8563_clkout_set_rate,
    368};
    369
    370static struct clk *hym8563_clkout_register_clk(struct hym8563 *hym8563)
    371{
    372	struct i2c_client *client = hym8563->client;
    373	struct device_node *node = client->dev.of_node;
    374	struct clk *clk;
    375	struct clk_init_data init;
    376	int ret;
    377
    378	ret = i2c_smbus_write_byte_data(client, HYM8563_CLKOUT,
    379						0);
    380	if (ret < 0)
    381		return ERR_PTR(ret);
    382
    383	init.name = "hym8563-clkout";
    384	init.ops = &hym8563_clkout_ops;
    385	init.flags = 0;
    386	init.parent_names = NULL;
    387	init.num_parents = 0;
    388	hym8563->clkout_hw.init = &init;
    389
    390	/* optional override of the clockname */
    391	of_property_read_string(node, "clock-output-names", &init.name);
    392
    393	/* register the clock */
    394	clk = clk_register(&client->dev, &hym8563->clkout_hw);
    395
    396	if (!IS_ERR(clk))
    397		of_clk_add_provider(node, of_clk_src_simple_get, clk);
    398
    399	return clk;
    400}
    401#endif
    402
    403/*
    404 * The alarm interrupt is implemented as a level-low interrupt in the
    405 * hym8563, while the timer interrupt uses a falling edge.
    406 * We don't use the timer at all, so the interrupt is requested to
    407 * use the level-low trigger.
    408 */
    409static irqreturn_t hym8563_irq(int irq, void *dev_id)
    410{
    411	struct hym8563 *hym8563 = (struct hym8563 *)dev_id;
    412	struct i2c_client *client = hym8563->client;
    413	int data, ret;
    414
    415	rtc_lock(hym8563->rtc);
    416
    417	/* Clear the alarm flag */
    418
    419	data = i2c_smbus_read_byte_data(client, HYM8563_CTL2);
    420	if (data < 0) {
    421		dev_err(&client->dev, "%s: error reading i2c data %d\n",
    422			__func__, data);
    423		goto out;
    424	}
    425
    426	data &= ~HYM8563_CTL2_AF;
    427
    428	ret = i2c_smbus_write_byte_data(client, HYM8563_CTL2, data);
    429	if (ret < 0) {
    430		dev_err(&client->dev, "%s: error writing i2c data %d\n",
    431			__func__, ret);
    432	}
    433
    434out:
    435	rtc_unlock(hym8563->rtc);
    436	return IRQ_HANDLED;
    437}
    438
    439static int hym8563_init_device(struct i2c_client *client)
    440{
    441	int ret;
    442
    443	/* Clear stop flag if present */
    444	ret = i2c_smbus_write_byte_data(client, HYM8563_CTL1, 0);
    445	if (ret < 0)
    446		return ret;
    447
    448	ret = i2c_smbus_read_byte_data(client, HYM8563_CTL2);
    449	if (ret < 0)
    450		return ret;
    451
    452	/* Disable alarm and timer interrupts */
    453	ret &= ~HYM8563_CTL2_AIE;
    454	ret &= ~HYM8563_CTL2_TIE;
    455
    456	/* Clear any pending alarm and timer flags */
    457	if (ret & HYM8563_CTL2_AF)
    458		ret &= ~HYM8563_CTL2_AF;
    459
    460	if (ret & HYM8563_CTL2_TF)
    461		ret &= ~HYM8563_CTL2_TF;
    462
    463	ret &= ~HYM8563_CTL2_TI_TP;
    464
    465	return i2c_smbus_write_byte_data(client, HYM8563_CTL2, ret);
    466}
    467
    468#ifdef CONFIG_PM_SLEEP
    469static int hym8563_suspend(struct device *dev)
    470{
    471	struct i2c_client *client = to_i2c_client(dev);
    472	int ret;
    473
    474	if (device_may_wakeup(dev)) {
    475		ret = enable_irq_wake(client->irq);
    476		if (ret) {
    477			dev_err(dev, "enable_irq_wake failed, %d\n", ret);
    478			return ret;
    479		}
    480	}
    481
    482	return 0;
    483}
    484
    485static int hym8563_resume(struct device *dev)
    486{
    487	struct i2c_client *client = to_i2c_client(dev);
    488
    489	if (device_may_wakeup(dev))
    490		disable_irq_wake(client->irq);
    491
    492	return 0;
    493}
    494#endif
    495
    496static SIMPLE_DEV_PM_OPS(hym8563_pm_ops, hym8563_suspend, hym8563_resume);
    497
    498static int hym8563_probe(struct i2c_client *client,
    499			 const struct i2c_device_id *id)
    500{
    501	struct hym8563 *hym8563;
    502	int ret;
    503
    504	hym8563 = devm_kzalloc(&client->dev, sizeof(*hym8563), GFP_KERNEL);
    505	if (!hym8563)
    506		return -ENOMEM;
    507
    508	hym8563->rtc = devm_rtc_allocate_device(&client->dev);
    509	if (IS_ERR(hym8563->rtc))
    510		return PTR_ERR(hym8563->rtc);
    511
    512	hym8563->client = client;
    513	i2c_set_clientdata(client, hym8563);
    514
    515	ret = hym8563_init_device(client);
    516	if (ret) {
    517		dev_err(&client->dev, "could not init device, %d\n", ret);
    518		return ret;
    519	}
    520
    521	if (client->irq > 0) {
    522		ret = devm_request_threaded_irq(&client->dev, client->irq,
    523						NULL, hym8563_irq,
    524						IRQF_TRIGGER_LOW | IRQF_ONESHOT,
    525						client->name, hym8563);
    526		if (ret < 0) {
    527			dev_err(&client->dev, "irq %d request failed, %d\n",
    528				client->irq, ret);
    529			return ret;
    530		}
    531	}
    532
    533	if (client->irq > 0 ||
    534	    device_property_read_bool(&client->dev, "wakeup-source")) {
    535		device_init_wakeup(&client->dev, true);
    536	}
    537
    538	/* check state of calendar information */
    539	ret = i2c_smbus_read_byte_data(client, HYM8563_SEC);
    540	if (ret < 0)
    541		return ret;
    542
    543	dev_dbg(&client->dev, "rtc information is %s\n",
    544		(ret & HYM8563_SEC_VL) ? "invalid" : "valid");
    545
    546	hym8563->rtc->ops = &hym8563_rtc_ops;
    547	set_bit(RTC_FEATURE_ALARM_RES_MINUTE, hym8563->rtc->features);
    548	clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, hym8563->rtc->features);
    549
    550#ifdef CONFIG_COMMON_CLK
    551	hym8563_clkout_register_clk(hym8563);
    552#endif
    553
    554	return devm_rtc_register_device(hym8563->rtc);
    555}
    556
    557static const struct i2c_device_id hym8563_id[] = {
    558	{ "hym8563", 0 },
    559	{},
    560};
    561MODULE_DEVICE_TABLE(i2c, hym8563_id);
    562
    563static const struct of_device_id hym8563_dt_idtable[] = {
    564	{ .compatible = "haoyu,hym8563" },
    565	{},
    566};
    567MODULE_DEVICE_TABLE(of, hym8563_dt_idtable);
    568
    569static struct i2c_driver hym8563_driver = {
    570	.driver		= {
    571		.name	= "rtc-hym8563",
    572		.pm	= &hym8563_pm_ops,
    573		.of_match_table	= hym8563_dt_idtable,
    574	},
    575	.probe		= hym8563_probe,
    576	.id_table	= hym8563_id,
    577};
    578
    579module_i2c_driver(hym8563_driver);
    580
    581MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
    582MODULE_DESCRIPTION("HYM8563 RTC driver");
    583MODULE_LICENSE("GPL");