This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM335x RTC-only mode

Other Parts Discussed in Thread: AM3359

Hi,

I am developing am3359 board based on BeagleBone White schematic.
My board uses battery powering and works under Linux (ti-sdk-am335x-evm-07.00.00.00,
kernel 3.12.10).
I need save real time when board is switched off.
As I understand from TRM (section 8.1.4.3.5), I should use RTC-Only mode.
How can I use this mode under Linux?

Regards,
Oleg.

  • Hi,

    Please read sections 8.1.4.3.5 and 20.3.3.8 from the AM335x TRM Rev. O.
  • Hi, Biser

    Thank you for quick response.
    I already read this sections.
    I know about pmic_power_en and ext_wakeup signals (as written in 20.3.3.8).

    As I understand, Beaglebone schematic is ready for RTC-only mode. And there is not need any hardware modifications.
    Is it right?

    I use ti-sdk-am335x-evm-07.00.00.00 (kernel 3.12.10) out-of-box:
    ...
    [ 0.000000] Booting Linux on physical CPU 0x0
    [ 0.000000] Linux version 3.12.10-ti2013.12.01 (jenkins@sdit-build02) (gcc version 4.7.3 20130226 (prerelease) (crosstool-NG linaro-1.13.1-4.7-2013.03-20130313 - Linaro GCC 2013.03) ) #1 Mon Mar 24 09:25:56 CDT 2014
    [ 0.000000] CPU: ARMv7 Processor [413fc082] revision 2 (ARMv7), cr=10c53c7d
    [ 0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
    [ 0.000000] Machine: Generic AM33XX (Flattened Device Tree), model: TI AM335x BeagleBone
    ...

    When I will send poweroff command under Linux I will not get RTC-only mode out-of-box.
    Is it right?

    So I need to modify software for RTC-only mode. Right?
    What is your recommendations?

    Best Regards,
    Oleg.
  • Yes, the BB White hardware is wired to support RTC-only mode. I have notified the software team to comment also. They will respond here.
  • Hi Oleg,

    Have a look at the following thread:
    e2e.ti.com/.../1405580

    Best Regards,
    Yordan
  • Hi, Yordan

    Thank you for link.
    I will test and report about results.

    Best Regards,
    Oleg.
  • Hi, Yordan

    I had read links.
    This driver is compatible with old kernel (3.2.x and so on) without device tree.
    So I added rtc-omap driver in linux-3.2.0-psp04.06.00.08.sdk,
    compiled driver and checked with my board.
    It works.

    Then I modifed this driver for 3.12.10 kernel with dtb.
    (I attached driver and dts files).
    It works also.

    I tested 3.12.10 kernel not only my board, but Beaglebone Black too.
    When I send poweroff command, Beaglebone Black is entered into RTC-only mode
    (only RTC rail is powered, other rails is powered off, 32 kHz clock is present).

    But I watch 40 mA current in RTC-only mode (instead of expected 1 mA) for Beaglebone Black.
    Why?

    What is your advice?

    Regards,
    Oleg.

    /*
     * TI OMAP1 Real Time Clock interface for Linux
     *
     * Copyright (C) 2003 MontaVista Software, Inc.
     * Author: George G. Davis <gdavis@mvista.com> or <source@mvista.com>
     *
     * Copyright (C) 2006 David Brownell (new RTC framework)
     *
     * This program is free software; you can redistribute it and/or
     * modify it under the terms of the GNU General Public License
     * as published by the Free Software Foundation; either version
     * 2 of the License, or (at your option) any later version.
     */
    
    #include <linux/kernel.h>
    #include <linux/init.h>
    #include <linux/module.h>
    #include <linux/ioport.h>
    #include <linux/delay.h>
    #include <linux/rtc.h>
    #include <linux/bcd.h>
    #include <linux/platform_device.h>
    #include <linux/of.h>
    #include <linux/of_device.h>
    #include <linux/pm_runtime.h>
    #include <linux/io.h>
    
    /* The OMAP1 RTC is a year/month/day/hours/minutes/seconds BCD clock
     * with century-range alarm matching, driven by the 32kHz clock.
     *
     * The main user-visible ways it differs from PC RTCs are by omitting
     * "don't care" alarm fields and sub-second periodic IRQs, and having
     * an autoadjust mechanism to calibrate to the true oscillator rate.
     *
     * Board-specific wiring options include using split power mode with
     * RTC_OFF_NOFF used as the reset signal (so the RTC won't be reset),
     * and wiring RTC_WAKE_INT (so the RTC alarm can wake the system from
     * low power modes) for OMAP1 boards (OMAP-L138 has this built into
     * the SoC). See the BOARD-SPECIFIC CUSTOMIZATION comment.
     */
    
    #define	DRIVER_NAME			"omap_rtc"
    
    #define OMAP_RTC_BASE			0xfffb4800
    
    /* RTC registers */
    #define OMAP_RTC_SECONDS_REG		0x00
    #define OMAP_RTC_MINUTES_REG		0x04
    #define OMAP_RTC_HOURS_REG		0x08
    #define OMAP_RTC_DAYS_REG		0x0C
    #define OMAP_RTC_MONTHS_REG		0x10
    #define OMAP_RTC_YEARS_REG		0x14
    #define OMAP_RTC_WEEKS_REG		0x18
    
    #define OMAP_RTC_ALARM_SECONDS_REG	0x20
    #define OMAP_RTC_ALARM_MINUTES_REG	0x24
    #define OMAP_RTC_ALARM_HOURS_REG	0x28
    #define OMAP_RTC_ALARM_DAYS_REG		0x2c
    #define OMAP_RTC_ALARM_MONTHS_REG	0x30
    #define OMAP_RTC_ALARM_YEARS_REG	0x34
    
    #define OMAP_RTC_CTRL_REG		0x40
    #define OMAP_RTC_STATUS_REG		0x44
    #define OMAP_RTC_INTERRUPTS_REG		0x48
    
    #define OMAP_RTC_COMP_LSB_REG		0x4c
    #define OMAP_RTC_COMP_MSB_REG		0x50
    #define OMAP_RTC_OSC_REG		0x54
    
    #define OMAP_RTC_KICK0_REG		0x6c
    #define OMAP_RTC_KICK1_REG		0x70
    
    #define OMAP_RTC_IRQWAKEEN		0x7c
    
    #define OMAP_RTC_ALARM2_SECONDS_REG	0x80
    #define OMAP_RTC_ALARM2_MINUTES_REG	0x84
    #define OMAP_RTC_ALARM2_HOURS_REG	0x88
    #define OMAP_RTC_ALARM2_DAYS_REG	0x8C
    #define OMAP_RTC_ALARM2_MONTHS_REG	0x90
    #define OMAP_RTC_ALARM2_YEARS_REG	0x94
    #define OMAP_RTC_PMIC_REG		0x98
    
    /* OMAP_RTC_CTRL_REG bit fields: */
    #define OMAP_RTC_CTRL_SPLIT		(1<<7)
    #define OMAP_RTC_CTRL_DISABLE		(1<<6)
    #define OMAP_RTC_CTRL_SET_32_COUNTER	(1<<5)
    #define OMAP_RTC_CTRL_TEST		(1<<4)
    #define OMAP_RTC_CTRL_MODE_12_24	(1<<3)
    #define OMAP_RTC_CTRL_AUTO_COMP		(1<<2)
    #define OMAP_RTC_CTRL_ROUND_30S		(1<<1)
    #define OMAP_RTC_CTRL_STOP		(1<<0)
    
    /* OMAP_RTC_STATUS_REG bit fields: */
    #define OMAP_RTC_STATUS_POWER_UP        (1<<7)
    #define OMAP_RTC_STATUS_ALARM           (1<<6)
    #define OMAP_RTC_STATUS_1D_EVENT        (1<<5)
    #define OMAP_RTC_STATUS_1H_EVENT        (1<<4)
    #define OMAP_RTC_STATUS_1M_EVENT        (1<<3)
    #define OMAP_RTC_STATUS_1S_EVENT        (1<<2)
    #define OMAP_RTC_STATUS_RUN             (1<<1)
    #define OMAP_RTC_STATUS_BUSY            (1<<0)
    
    /* OMAP_RTC_INTERRUPTS_REG bit fields: */
    #define OMAP_RTC_INTERRUPTS_IT_ALARM2	(1<<4)
    #define OMAP_RTC_INTERRUPTS_IT_ALARM    (1<<3)
    #define OMAP_RTC_INTERRUPTS_IT_TIMER    (1<<2)
    
    /* OMAP_RTC_IRQWAKEEN bit fields: */
    #define OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN    (1<<1)
    
    /* OMAP_RTC_KICKER values */
    #define	KICK0_VALUE			0x83e70b13
    #define	KICK1_VALUE			0x95a4f1e0
    
    #define	OMAP_RTC_HAS_KICKER		0x1
    
    /*
     * Few RTC IP revisions has special WAKE-EN Register to enable Wakeup
     * generation for event Alarm.
     */
    #define	OMAP_RTC_HAS_IRQWAKEEN		0x2
    
    /* OMAP_RTC_PMIC_REG bit fields: */
    #define OMAP_RTC_PMIC_POWER_EN_EN 	(1<<16)
    #define SHUTDOWN_TIME_SEC 		2
    #define SECS_IN_MIN 			60
    #define WAIT_AFTER 			(SECS_IN_MIN - SHUTDOWN_TIME_SEC)
    #define WAIT_TIME_MS 			(SHUTDOWN_TIME_SEC * 1000)
    
    static void __iomem	*rtc_base;
    
    #define rtc_read(addr)		readb(rtc_base + (addr))
    #define rtc_write(val, addr)	writeb(val, rtc_base + (addr))
    
    #define rtc_writel(val, addr)	writel(val, rtc_base + (addr))
    
    
    /* we rely on the rtc framework to handle locking (rtc->ops_lock),
     * so the only other requirement is that register accesses which
     * require BUSY to be clear are made with IRQs locally disabled
     */
    static void rtc_wait_not_busy(void)
    {
    	int	count = 0;
    	u8	status;
    
    	/* BUSY may stay active for 1/32768 second (~30 usec) */
    	for (count = 0; count < 50; count++) {
    		status = rtc_read(OMAP_RTC_STATUS_REG);
    		if ((status & (u8)OMAP_RTC_STATUS_BUSY) == 0)
    			break;
    		udelay(1);
    	}
    	/* now we have ~15 usec to read/write various registers */
    }
    
    static irqreturn_t rtc_irq(int irq, void *rtc)
    {
    	unsigned long		events = 0;
    	u8			irq_data;
    
    	irq_data = rtc_read(OMAP_RTC_STATUS_REG);
    
    	/* alarm irq? */
    	if (irq_data & OMAP_RTC_STATUS_ALARM) {
    		rtc_write(OMAP_RTC_STATUS_ALARM, OMAP_RTC_STATUS_REG);
    		events |= RTC_IRQF | RTC_AF;
    	}
    
    	/* 1/sec periodic/update irq? */
    	if (irq_data & OMAP_RTC_STATUS_1S_EVENT)
    		events |= RTC_IRQF | RTC_UF;
    
    	rtc_update_irq(rtc, 1, events);
    
    	return IRQ_HANDLED;
    }
    
    static int omap_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
    {
    	u8 reg;
    
    	local_irq_disable();
    	rtc_wait_not_busy();
    	reg = rtc_read(OMAP_RTC_INTERRUPTS_REG);
    	if (enabled)
    		reg |= OMAP_RTC_INTERRUPTS_IT_ALARM;
    	else
    		reg &= ~OMAP_RTC_INTERRUPTS_IT_ALARM;
    	rtc_wait_not_busy();
    	rtc_write(reg, OMAP_RTC_INTERRUPTS_REG);
    	local_irq_enable();
    
    	return 0;
    }
    
    /* this hardware doesn't support "don't care" alarm fields */
    static int tm2bcd(struct rtc_time *tm)
    {
    	if (rtc_valid_tm(tm) != 0)
    		return -EINVAL;
    
    	tm->tm_sec = bin2bcd(tm->tm_sec);
    	tm->tm_min = bin2bcd(tm->tm_min);
    	tm->tm_hour = bin2bcd(tm->tm_hour);
    	tm->tm_mday = bin2bcd(tm->tm_mday);
    
    	tm->tm_mon = bin2bcd(tm->tm_mon + 1);
    
    	/* epoch == 1900 */
    	if (tm->tm_year < 100 || tm->tm_year > 199)
    		return -EINVAL;
    	tm->tm_year = bin2bcd(tm->tm_year - 100);
    
    	return 0;
    }
    
    static void bcd2tm(struct rtc_time *tm)
    {
    	tm->tm_sec = bcd2bin(tm->tm_sec);
    	tm->tm_min = bcd2bin(tm->tm_min);
    	tm->tm_hour = bcd2bin(tm->tm_hour);
    	tm->tm_mday = bcd2bin(tm->tm_mday);
    	tm->tm_mon = bcd2bin(tm->tm_mon) - 1;
    	/* epoch == 1900 */
    	tm->tm_year = bcd2bin(tm->tm_year) + 100;
    }
    
    
    static int omap_rtc_read_time(struct device *dev, struct rtc_time *tm)
    {
    	/* we don't report wday/yday/isdst ... */
    	local_irq_disable();
    	rtc_wait_not_busy();
    
    	tm->tm_sec = rtc_read(OMAP_RTC_SECONDS_REG);
    	tm->tm_min = rtc_read(OMAP_RTC_MINUTES_REG);
    	tm->tm_hour = rtc_read(OMAP_RTC_HOURS_REG);
    	tm->tm_mday = rtc_read(OMAP_RTC_DAYS_REG);
    	tm->tm_mon = rtc_read(OMAP_RTC_MONTHS_REG);
    	tm->tm_year = rtc_read(OMAP_RTC_YEARS_REG);
    
    	local_irq_enable();
    
    	bcd2tm(tm);
    	return 0;
    }
    
    static int omap_rtc_set_time(struct device *dev, struct rtc_time *tm)
    {
    	if (tm2bcd(tm) < 0)
    		return -EINVAL;
    	local_irq_disable();
    	rtc_wait_not_busy();
    
    	rtc_write(tm->tm_year, OMAP_RTC_YEARS_REG);
    	rtc_write(tm->tm_mon, OMAP_RTC_MONTHS_REG);
    	rtc_write(tm->tm_mday, OMAP_RTC_DAYS_REG);
    	rtc_write(tm->tm_hour, OMAP_RTC_HOURS_REG);
    	rtc_write(tm->tm_min, OMAP_RTC_MINUTES_REG);
    	rtc_write(tm->tm_sec, OMAP_RTC_SECONDS_REG);
    
    	local_irq_enable();
    
    	return 0;
    }
    
    static int omap_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
    {
    	local_irq_disable();
    	rtc_wait_not_busy();
    
    	alm->time.tm_sec = rtc_read(OMAP_RTC_ALARM_SECONDS_REG);
    	alm->time.tm_min = rtc_read(OMAP_RTC_ALARM_MINUTES_REG);
    	alm->time.tm_hour = rtc_read(OMAP_RTC_ALARM_HOURS_REG);
    	alm->time.tm_mday = rtc_read(OMAP_RTC_ALARM_DAYS_REG);
    	alm->time.tm_mon = rtc_read(OMAP_RTC_ALARM_MONTHS_REG);
    	alm->time.tm_year = rtc_read(OMAP_RTC_ALARM_YEARS_REG);
    
    	local_irq_enable();
    
    	bcd2tm(&alm->time);
    	alm->enabled = !!(rtc_read(OMAP_RTC_INTERRUPTS_REG)
    			& OMAP_RTC_INTERRUPTS_IT_ALARM);
    
    	return 0;
    }
    
    static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
    {
    	u8 reg;
    
    	if (tm2bcd(&alm->time) < 0)
    		return -EINVAL;
    
    	local_irq_disable();
    	rtc_wait_not_busy();
    
    	rtc_write(alm->time.tm_year, OMAP_RTC_ALARM_YEARS_REG);
    	rtc_write(alm->time.tm_mon, OMAP_RTC_ALARM_MONTHS_REG);
    	rtc_write(alm->time.tm_mday, OMAP_RTC_ALARM_DAYS_REG);
    	rtc_write(alm->time.tm_hour, OMAP_RTC_ALARM_HOURS_REG);
    	rtc_write(alm->time.tm_min, OMAP_RTC_ALARM_MINUTES_REG);
    	rtc_write(alm->time.tm_sec, OMAP_RTC_ALARM_SECONDS_REG);
    
    	reg = rtc_read(OMAP_RTC_INTERRUPTS_REG);
    	if (alm->enabled)
    		reg |= OMAP_RTC_INTERRUPTS_IT_ALARM;
    	else
    		reg &= ~OMAP_RTC_INTERRUPTS_IT_ALARM;
    	rtc_write(reg, OMAP_RTC_INTERRUPTS_REG);
    
    	local_irq_enable();
    
    	return 0;
    }
    
    /*
    * rtc_power_off: Set the pmic power off sequence. The RTC generates
    * pmic_pwr_enable control, which can be used to control an external
    * PMIC.
    */
    static void rtc_power_off(void)
    {
    	u32 val;
    	struct rtc_time tm;
    
    	/* Set PMIC power enable */
    	val = readl(rtc_base + OMAP_RTC_PMIC_REG);
    	writel(val | OMAP_RTC_PMIC_POWER_EN_EN, rtc_base + OMAP_RTC_PMIC_REG);
    
    	/* Wait few seconds instead of rollover */
    	do {
    		omap_rtc_read_time(NULL, &tm);
    		if (WAIT_AFTER <= tm.tm_sec)
    			mdelay(WAIT_TIME_MS);
    	} while (WAIT_AFTER <= tm.tm_sec);
    
    	/* Add shutdown time to the current value */
    	tm.tm_sec += SHUTDOWN_TIME_SEC;
    	if (tm2bcd(&tm) < 0)
    		return;
    
    	pr_info("System will go to power_off state in approx. %d secs\n",
    		SHUTDOWN_TIME_SEC);
    
    	/* Set the ALARM2 time */
    	rtc_write(tm.tm_sec, OMAP_RTC_ALARM2_SECONDS_REG);
    	rtc_write(tm.tm_min, OMAP_RTC_ALARM2_MINUTES_REG);
    	rtc_write(tm.tm_hour, OMAP_RTC_ALARM2_HOURS_REG);
    	rtc_write(tm.tm_mday, OMAP_RTC_ALARM2_DAYS_REG);
    	rtc_write(tm.tm_mon, OMAP_RTC_ALARM2_MONTHS_REG);
    	rtc_write(tm.tm_year, OMAP_RTC_ALARM2_YEARS_REG);
    
    	/* Enable alarm2 interrupt */
    	val = readl(rtc_base + OMAP_RTC_INTERRUPTS_REG);
    	writel(val | OMAP_RTC_INTERRUPTS_IT_ALARM2,
    		rtc_base + OMAP_RTC_INTERRUPTS_REG);
    
    	/* Do not allow to execute any other task */
    	while (1);
    }
    
    static struct rtc_class_ops omap_rtc_ops = {
    	.read_time	= omap_rtc_read_time,
    	.set_time	= omap_rtc_set_time,
    	.read_alarm	= omap_rtc_read_alarm,
    	.set_alarm	= omap_rtc_set_alarm,
    	.alarm_irq_enable = omap_rtc_alarm_irq_enable,
    };
    
    static int omap_rtc_alarm;
    static int omap_rtc_timer;
    static bool is_pmic_controller = false;
    
    #define	OMAP_RTC_DATA_AM3352_IDX	1
    #define	OMAP_RTC_DATA_DA830_IDX		2
    
    static struct platform_device_id omap_rtc_devtype[] = {
    	{
    		.name	= DRIVER_NAME,
    	},
    	[OMAP_RTC_DATA_AM3352_IDX] = {
    		.name	= "am3352-rtc",
    		.driver_data = OMAP_RTC_HAS_KICKER | OMAP_RTC_HAS_IRQWAKEEN,
    	},
    	[OMAP_RTC_DATA_DA830_IDX] = {
    		.name	= "da830-rtc",
    		.driver_data = OMAP_RTC_HAS_KICKER,
    	},
    	{},
    };
    MODULE_DEVICE_TABLE(platform, omap_rtc_devtype);
    
    static const struct of_device_id omap_rtc_of_match[] = {
    	{	.compatible	= "ti,da830-rtc",
    		.data		= &omap_rtc_devtype[OMAP_RTC_DATA_DA830_IDX],
    	},
    	{	.compatible	= "ti,am3352-rtc",
    		.data		= &omap_rtc_devtype[OMAP_RTC_DATA_AM3352_IDX],
    	},
    	{},
    };
    MODULE_DEVICE_TABLE(of, omap_rtc_of_match);
    
    static int __init omap_rtc_probe(struct platform_device *pdev)
    {
    	struct resource		*res;
    	struct rtc_device	*rtc;
    	u8			reg, new_ctrl;
    	const struct platform_device_id *id_entry;
    	const struct of_device_id *of_id;
    
    	of_id = of_match_device(omap_rtc_of_match, &pdev->dev);
    	if (of_id) {
    		pdev->id_entry = of_id->data;
    		is_pmic_controller = of_property_read_bool(pdev->dev.of_node,
    					"system-power-controller");
    	}
    
    	omap_rtc_timer = platform_get_irq(pdev, 0);
    	if (omap_rtc_timer <= 0) {
    		pr_debug("%s: no update irq?\n", pdev->name);
    		return -ENOENT;
    	}
    
    	omap_rtc_alarm = platform_get_irq(pdev, 1);
    	if (omap_rtc_alarm <= 0) {
    		pr_debug("%s: no alarm irq?\n", pdev->name);
    		return -ENOENT;
    	}
    
    	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    	rtc_base = devm_ioremap_resource(&pdev->dev, res);
    	if (IS_ERR(rtc_base))
    		return PTR_ERR(rtc_base);
    
    	/* Enable the clock/module so that we can access the registers */
    	pm_runtime_enable(&pdev->dev);
    	pm_runtime_get_sync(&pdev->dev);
    
    	id_entry = platform_get_device_id(pdev);
    	if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER)) {
    		rtc_writel(KICK0_VALUE, OMAP_RTC_KICK0_REG);
    		rtc_writel(KICK1_VALUE, OMAP_RTC_KICK1_REG);
    	}
    
    	rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
    			&omap_rtc_ops, THIS_MODULE);
    	if (IS_ERR(rtc)) {
    		pr_debug("%s: can't register RTC device, err %ld\n",
    			pdev->name, PTR_ERR(rtc));
    		goto fail0;
    	}
    	platform_set_drvdata(pdev, rtc);
    
    	/* RTC power off */
    	if (is_pmic_controller && !pm_power_off)
    			pm_power_off = rtc_power_off;
    
    	/* clear pending irqs, and set 1/second periodic,
    	 * which we'll use instead of update irqs
    	 */
    	rtc_write(0, OMAP_RTC_INTERRUPTS_REG);
    
    	/* Selecting CLK cource for RTC */
    	rtc_writel((1 << 3) | (1 << 6), OMAP_RTC_OSC_REG);
    	rtc_writel(0x3, OMAP_RTC_IRQWAKEEN);
    
    	/* clear old status */
    	reg = rtc_read(OMAP_RTC_STATUS_REG);
    	if (reg & (u8) OMAP_RTC_STATUS_POWER_UP) {
    		pr_info("%s: RTC power up reset detected\n",
    			pdev->name);
    		rtc_write(OMAP_RTC_STATUS_POWER_UP, OMAP_RTC_STATUS_REG);
    	}
    	if (reg & (u8) OMAP_RTC_STATUS_ALARM)
    		rtc_write(OMAP_RTC_STATUS_ALARM, OMAP_RTC_STATUS_REG);
    
    	/* handle periodic and alarm irqs */
    	if (devm_request_irq(&pdev->dev, omap_rtc_timer, rtc_irq, 0,
    			dev_name(&rtc->dev), rtc)) {
    		pr_debug("%s: RTC timer interrupt IRQ%d already claimed\n",
    			pdev->name, omap_rtc_timer);
    		goto fail0;
    	}
    	if ((omap_rtc_timer != omap_rtc_alarm) &&
    		(devm_request_irq(&pdev->dev, omap_rtc_alarm, rtc_irq, 0,
    			dev_name(&rtc->dev), rtc))) {
    		pr_debug("%s: RTC alarm interrupt IRQ%d already claimed\n",
    			pdev->name, omap_rtc_alarm);
    		goto fail0;
    	}
    
    	/* On boards with split power, RTC_ON_NOFF won't reset the RTC */
    	reg = rtc_read(OMAP_RTC_CTRL_REG);
    	if (reg & (u8) OMAP_RTC_CTRL_STOP)
    		pr_info("%s: already running\n", pdev->name);
    
    	/* force to 24 hour mode */
    	new_ctrl = reg & (OMAP_RTC_CTRL_SPLIT|OMAP_RTC_CTRL_AUTO_COMP);
    	new_ctrl |= OMAP_RTC_CTRL_STOP;
    
    	/* BOARD-SPECIFIC CUSTOMIZATION CAN GO HERE:
    	 *
    	 *  - Device wake-up capability setting should come through chip
    	 *    init logic. OMAP1 boards should initialize the "wakeup capable"
    	 *    flag in the platform device if the board is wired right for
    	 *    being woken up by RTC alarm. For OMAP-L138, this capability
    	 *    is built into the SoC by the "Deep Sleep" capability.
    	 *
    	 *  - Boards wired so RTC_ON_nOFF is used as the reset signal,
    	 *    rather than nPWRON_RESET, should forcibly enable split
    	 *    power mode.  (Some chip errata report that RTC_CTRL_SPLIT
    	 *    is write-only, and always reads as zero...)
    	 */
    
    	device_init_wakeup(&pdev->dev, true);
    
    	if (new_ctrl & (u8) OMAP_RTC_CTRL_SPLIT)
    		pr_info("%s: split power mode\n", pdev->name);
    
    	if (reg != new_ctrl)
    		rtc_write(new_ctrl, OMAP_RTC_CTRL_REG);
    
    	return 0;
    
    fail0:
    	if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER))
    		rtc_writel(0, OMAP_RTC_KICK0_REG);
    	pm_runtime_put_sync(&pdev->dev);
    	pm_runtime_disable(&pdev->dev);
    	return -EIO;
    }
    
    static int __exit omap_rtc_remove(struct platform_device *pdev)
    {
    	const struct platform_device_id *id_entry =
    				platform_get_device_id(pdev);
    
    	device_init_wakeup(&pdev->dev, 0);
    
    	/* leave rtc running, but disable irqs */
    	rtc_write(0, OMAP_RTC_INTERRUPTS_REG);
    
    	if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER))
    		rtc_writel(0, OMAP_RTC_KICK0_REG);
    
    	/* Disable the clock/module */
    	pm_runtime_put_sync(&pdev->dev);
    	pm_runtime_disable(&pdev->dev);
    
    	return 0;
    }
    
    #ifdef CONFIG_PM_SLEEP
    static u8 irqstat;
    
    static int omap_rtc_suspend(struct device *dev)
    {
    	u8 irqwake_stat;
    	struct platform_device *pdev = to_platform_device(dev);
    	const struct platform_device_id *id_entry =
    					platform_get_device_id(pdev);
    
    	irqstat = rtc_read(OMAP_RTC_INTERRUPTS_REG);
    
    	/* FIXME the RTC alarm is not currently acting as a wakeup event
    	 * source on some platforms, and in fact this enable() call is just
    	 * saving a flag that's never used...
    	 */
    	if (device_may_wakeup(dev)) {
    		enable_irq_wake(omap_rtc_alarm);
    
    		if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN) {
    			irqwake_stat = rtc_read(OMAP_RTC_IRQWAKEEN);
    			irqwake_stat |= OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN;
    			rtc_write(irqwake_stat, OMAP_RTC_IRQWAKEEN);
    		}
    	} else {
    		rtc_write(0, OMAP_RTC_INTERRUPTS_REG);
    	}
    
    	/* Disable the clock/module */
    	pm_runtime_put_sync(dev);
    
    	return 0;
    }
    
    static int omap_rtc_resume(struct device *dev)
    {
    	u8 irqwake_stat;
    	struct platform_device *pdev = to_platform_device(dev);
    	const struct platform_device_id *id_entry =
    				platform_get_device_id(pdev);
    
    	/* Enable the clock/module so that we can access the registers */
    	pm_runtime_get_sync(dev);
    
    	if (device_may_wakeup(dev)) {
    		disable_irq_wake(omap_rtc_alarm);
    
    		if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN) {
    			irqwake_stat = rtc_read(OMAP_RTC_IRQWAKEEN);
    			irqwake_stat &= ~OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN;
    			rtc_write(irqwake_stat, OMAP_RTC_IRQWAKEEN);
    		}
    	} else {
    		rtc_write(irqstat, OMAP_RTC_INTERRUPTS_REG);
    	}
    	return 0;
    }
    #endif
    
    static SIMPLE_DEV_PM_OPS(omap_rtc_pm_ops, omap_rtc_suspend, omap_rtc_resume);
    
    static void omap_rtc_shutdown(struct platform_device *pdev)
    {
    	rtc_write(0, OMAP_RTC_INTERRUPTS_REG);
    }
    
    MODULE_ALIAS("platform:omap_rtc");
    static struct platform_driver omap_rtc_driver = {
    	.remove		= __exit_p(omap_rtc_remove),
    	.shutdown	= omap_rtc_shutdown,
    	.driver		= {
    		.name	= DRIVER_NAME,
    		.owner	= THIS_MODULE,
    		.pm	= &omap_rtc_pm_ops,
    		.of_match_table = of_match_ptr(omap_rtc_of_match),
    	},
    	.id_table	= omap_rtc_devtype,
    };
    
    module_platform_driver_probe(omap_rtc_driver, omap_rtc_probe);
    
    MODULE_AUTHOR("George G. Davis (and others)");
    MODULE_LICENSE("GPL");
    
    /*
     * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
     *
     * 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.
     */
    /dts-v1/;
    
    #include "am33xx.dtsi"
    #include "am335x-bone-common.dtsi"
    
    &ldo3_reg {
    	regulator-min-microvolt = <1800000>;
    	regulator-max-microvolt = <1800000>;
    	regulator-always-on;
    };
    
    &mmc1 {
    	vmmc-supply = <&vmmcsd_fixed>;
    };
    
    &mmc2 {
    	vmmc-supply = <&vmmcsd_fixed>;
    	pinctrl-names = "default";
    	pinctrl-0 = <&emmc_pins>;
    	bus-width = <8>;
    	ti,non-removable;
    	status = "okay";
    };
    
    &am33xx_pinmux {
    	nxp_hdmi_bonelt_pins: nxp_hdmi_bonelt_pins {
    		pinctrl-single,pins = <
    			0x1b0 0x03      /* xdma_event_intr0, OMAP_MUX_MODE3 | AM33XX_PIN_OUTPUT */
    			0xa0 0x08       /* lcd_data0.lcd_data0, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
    			0xa4 0x08       /* lcd_data1.lcd_data1, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
    			0xa8 0x08       /* lcd_data2.lcd_data2, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
    			0xac 0x08       /* lcd_data3.lcd_data3, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
    			0xb0 0x08       /* lcd_data4.lcd_data4, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
    			0xb4 0x08       /* lcd_data5.lcd_data5, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
    			0xb8 0x08       /* lcd_data6.lcd_data6, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
    			0xbc 0x08       /* lcd_data7.lcd_data7, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
    			0xc0 0x08       /* lcd_data8.lcd_data8, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
    			0xc4 0x08       /* lcd_data9.lcd_data9, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
    			0xc8 0x08       /* lcd_data10.lcd_data10, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
    			0xcc 0x08       /* lcd_data11.lcd_data11, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
    			0xd0 0x08       /* lcd_data12.lcd_data12, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
    			0xd4 0x08       /* lcd_data13.lcd_data13, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
    			0xd8 0x08       /* lcd_data14.lcd_data14, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
    			0xdc 0x08       /* lcd_data15.lcd_data15, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
    			0xe0 0x00       /* lcd_vsync.lcd_vsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
    			0xe4 0x00       /* lcd_hsync.lcd_hsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
    			0xe8 0x00       /* lcd_pclk.lcd_pclk, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
    			0xec 0x00       /* lcd_ac_bias_en.lcd_ac_bias_en, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
    		>;
    	};
    	nxp_hdmi_bonelt_off_pins: nxp_hdmi_bonelt_off_pins {
    		pinctrl-single,pins = <
    			0x1b0 0x03      /* xdma_event_intr0, OMAP_MUX_MODE3 | AM33XX_PIN_OUTPUT */
    		>;
    	};
    };
    
    &i2c0 {
    	hdmi1: hdmi@70 {
    	      compatible = "nxp,tda998x";
    	      reg = <0x70>;
    	};
    };
    
    &lcdc {
    	pinctrl-names = "default", "off";
    	pinctrl-0 = <&nxp_hdmi_bonelt_pins>;
    	pinctrl-1 = <&nxp_hdmi_bonelt_off_pins>;
    	status = "okay";
    	hdmi = <&hdmi1>;
    	display-timings {
    		1280x720P60 {
    		   clock-frequency = <74250000>;
    		   hactive = <1280>;
    		   vactive = <720>;
    		   hfront-porch = <110>;
    		   hback-porch = <220>;
    		   hsync-len = <40>;
    		   vback-porch = <5>;
    		   vfront-porch = <20>;
    		   vsync-len = <5>;
    		   hsync-active = <1>;
    		   vsync-active = <1>;
    		};
    		640x480P60 {
    		   clock-frequency = <25200000>;
    		   hactive = <640>;
    		   vactive = <480>;
    		   hfront-porch = <16>;
    		   hback-porch = <48>;
    		   hsync-len = <96>;
    		   vback-porch = <31>;
    		   vfront-porch = <11>;
    		   vsync-len = <2>;
    		   hsync-active = <0>;
    		   vsync-active = <0>;
    		};
    	};
    };
    
    / {
    	ocp {
    		rtc@44e3e000 {
    			system-power-controller;
    		};
    	};
    };
    

  • Hi, Yordan

    I tested last version of TI SDK 03.01.00.06-Linux-x86 (kernel 4.4.19+gitAUTOINC+db0b54cdad-gdb0b54cdad) in RTC-only mode on Beaglebone Black.
    I used zImage out-of-box and commented "ti,pmic-shutdown-controller" line in "am335x-bone-common.dtsi" file (and compiled, of course):

    &tps {
        /*
         * Configure pmic to enter OFF-state instead of SLEEP-state ("RTC-only
         * mode") at poweroff.  Most BeagleBone versions do not support RTC-only
         * mode and risk hardware damage if this mode is entered.
         *
         * For details, see linux-omap mailing list May 2015 thread
         *    [PATCH] ARM: dts: am335x-bone* enable pmic-shutdown-controller
         * In particular, messages:
         *    www.spinics.net/.../msg118585.html
         *    www.spinics.net/.../msg118615.html
         *
         * You can override this later with
         *    &tps {  /delete-property/ ti,pmic-shutdown-controller;  }
         * if you want to use RTC-only mode and made sure you are not affected
         * by the hardware problems. (Tip: double-check by performing a current
         * measurement after shutdown: it should be less than 1 mA.)
         */
    //    ti,pmic-shutdown-controller;
    ...
    }


    Result is the same as in 3.12.10 kernel.
    RTC works after powering off, but current is 40 mA instead of declared 1 mA.
    What may be reason?

    Do you have ideas?

    Regards,
    Oleg.

     

  • Hi Oleg,

    No, I am out of ideas about this. I will consult the design team and get back as soon as I have any feedback.

    Best Regards,
    Yordan
  • Oleg,

    Does your device tree have an rtc node?

    BeagleBone White did not support rtc-only mode because those were primarily fitted with AM335x PG1.0, which had an rtc-only errata.  For EZSDK 7.0 (this is pre-processor sdk), you should still see an rtc node in the beaglebone-black dts which you can copy (assuming your custom board does not have AM335x PG1.0 silicon).  Future releases will have omitted the rtc node entirely because there was again a issue on the BeagleBone Black, which caused damage to the device.

    If the rtc node is missing in your SDK, check here for the original patch:

    [https://patchwork.kernel.org/patch/5060581/]

    Regards,
    Mike

  • Hi, Mike

    Thank you for quick response.

    I have two BeagleBone: White and Black.

    White rev. A6  has XAM3359ZCZ SoC.
    My developing board is based on BeagleBone White schematic and has AM3359BZCZA80 SoC.
    I didn't test RTC-only mode on BBW because it has FTDI console and can't be powered off normally (remains USB power).

    So I tested RTC mode on my custom board. When I got strange results, I began to test on BeagleBone Black.
    (It contains AM3358BZCZI100 SoC. That is 2.1 revision. Right?).

    My SDK 03.01.00.06 is already contains recommeded you patch and rtc node isn't missing (please see attached files: am335x-bone-common.dtsi, am335x-boneblack.dts).
    File am335x-bone-common.dtsi contains rtc node:
    &rtc {
        clocks = <&clk_32768_ck>, <&clkdiv32k_ick>;
        clock-names = "ext-clk", "int-clk";
        ti,system-power-controller;
    };

    I commented string "ti,pmic-shutdown-controller;" in this dtsi file too.

    I am sure that SoC goes to RTC-only mode, because I get the messages when send poweroff command:
    root@am335x-evm:~# poweroff
    ... /* systemd messages */
    [  201.224802] reboot: Power down
    [  201.227962] System will go to power_off state in approx. 1 second

    RTC driver (drivers/rtc/rtc-omap.c: omap_rtc_power_off_program() ) sends last message.
    Moreover, I inspected RTC rail and 32 kHz clock with oscilloscope.
    Only RTC rail is powered, other rails is powered off, 32 kHz clock is present.
    Therefore this mode works.

    But why so much current supply? (40 mA instead of 1 mA).

    Best regards,
    Oleg.

    /*
     * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
     *
     * 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.
     */
    
    / {
    	cpus {
    		cpu@0 {
    			cpu0-supply = <&dcdc2_reg>;
    		};
    	};
    
    	memory {
    		device_type = "memory";
    		reg = <0x80000000 0x10000000>; /* 256 MB */
    	};
    
    	leds {
    		pinctrl-names = "default", "sleep";
    		pinctrl-0 = <&user_leds_default>;
    		pinctrl-1 = <&user_leds_sleep>;
    
    		compatible = "gpio-leds";
    
    		led@2 {
    			label = "beaglebone:green:heartbeat";
    			gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>;
    			linux,default-trigger = "heartbeat";
    			default-state = "off";
    		};
    
    		led@3 {
    			label = "beaglebone:green:mmc0";
    			gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>;
    			linux,default-trigger = "mmc0";
    			default-state = "off";
    		};
    
    		led@4 {
    			label = "beaglebone:green:usr2";
    			gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>;
    			linux,default-trigger = "cpu0";
    			default-state = "off";
    		};
    
    		led@5 {
    			label = "beaglebone:green:usr3";
    			gpios = <&gpio1 24 GPIO_ACTIVE_HIGH>;
    			linux,default-trigger = "mmc1";
    			default-state = "off";
    		};
    	};
    
    	vmmcsd_fixed: fixedregulator@0 {
    		compatible = "regulator-fixed";
    		regulator-name = "vmmcsd_fixed";
    		regulator-min-microvolt = <3300000>;
    		regulator-max-microvolt = <3300000>;
    	};
    };
    
    &am33xx_pinmux {
    	pinctrl-names = "default";
    	pinctrl-0 = <&clkout2_pin>;
    
    	user_leds_default: user_leds_default {
    		pinctrl-single,pins = <
    			0x54 (PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* gpmc_a5.gpio1_21 */
    			0x58 (PIN_OUTPUT_PULLUP | MUX_MODE7)	/* gpmc_a6.gpio1_22 */
    			0x5c (PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* gpmc_a7.gpio1_23 */
    			0x60 (PIN_OUTPUT_PULLUP | MUX_MODE7)	/* gpmc_a8.gpio1_24 */
    		>;
    	};
    
    	user_leds_sleep: user_leds_sleep {
    		pinctrl-single,pins = <
    			0x54 (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_a5.gpio1_21 */
    			0x58 (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_a6.gpio1_22 */
    			0x5c (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_a7.gpio1_23 */
    			0x60 (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_a8.gpio1_24 */
    		>;
    	};
    
    	i2c0_pins: pinmux_i2c0_pins {
    		pinctrl-single,pins = <
    			0x188 (PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_sda.i2c0_sda */
    			0x18c (PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_scl.i2c0_scl */
    		>;
    	};
    
    	i2c2_pins: pinmux_i2c2_pins {
    		pinctrl-single,pins = <
    			0x178 (PIN_INPUT_PULLUP | MUX_MODE3)	/* uart1_ctsn.i2c2_sda */
    			0x17c (PIN_INPUT_PULLUP | MUX_MODE3)	/* uart1_rtsn.i2c2_scl */
    		>;
    	};
    
    	uart0_pins: pinmux_uart0_pins {
    		pinctrl-single,pins = <
    			0x170 (PIN_INPUT_PULLUP | MUX_MODE0)	/* uart0_rxd.uart0_rxd */
    			0x174 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* uart0_txd.uart0_txd */
    		>;
    	};
    
    	clkout2_pin: pinmux_clkout2_pin {
    		pinctrl-single,pins = <
    			0x1b4 (PIN_OUTPUT_PULLDOWN | MUX_MODE3)	/* xdma_event_intr1.clkout2 */
    		>;
    	};
    
    	cpsw_default: cpsw_default {
    		pinctrl-single,pins = <
    			/* Slave 1 */
    			0x110 (PIN_INPUT_PULLUP | MUX_MODE0)	/* mii1_rxerr.mii1_rxerr */
    			0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* mii1_txen.mii1_txen */
    			0x118 (PIN_INPUT_PULLUP | MUX_MODE0)	/* mii1_rxdv.mii1_rxdv */
    			0x11c (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* mii1_txd3.mii1_txd3 */
    			0x120 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* mii1_txd2.mii1_txd2 */
    			0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* mii1_txd1.mii1_txd1 */
    			0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* mii1_txd0.mii1_txd0 */
    			0x12c (PIN_INPUT_PULLUP | MUX_MODE0)	/* mii1_txclk.mii1_txclk */
    			0x130 (PIN_INPUT_PULLUP | MUX_MODE0)	/* mii1_rxclk.mii1_rxclk */
    			0x134 (PIN_INPUT_PULLUP | MUX_MODE0)	/* mii1_rxd3.mii1_rxd3 */
    			0x138 (PIN_INPUT_PULLUP | MUX_MODE0)	/* mii1_rxd2.mii1_rxd2 */
    			0x13c (PIN_INPUT_PULLUP | MUX_MODE0)	/* mii1_rxd1.mii1_rxd1 */
    			0x140 (PIN_INPUT_PULLUP | MUX_MODE0)	/* mii1_rxd0.mii1_rxd0 */
    		>;
    	};
    
    	cpsw_sleep: cpsw_sleep {
    		pinctrl-single,pins = <
    			/* Slave 1 reset value */
    			0x110 (PIN_INPUT_PULLDOWN | MUX_MODE7)
    			0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7)
    			0x118 (PIN_INPUT_PULLDOWN | MUX_MODE7)
    			0x11c (PIN_INPUT_PULLDOWN | MUX_MODE7)
    			0x120 (PIN_INPUT_PULLDOWN | MUX_MODE7)
    			0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7)
    			0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7)
    			0x12c (PIN_INPUT_PULLDOWN | MUX_MODE7)
    			0x130 (PIN_INPUT_PULLDOWN | MUX_MODE7)
    			0x134 (PIN_INPUT_PULLDOWN | MUX_MODE7)
    			0x138 (PIN_INPUT_PULLDOWN | MUX_MODE7)
    			0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7)
    			0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7)
    		>;
    	};
    
    	davinci_mdio_default: davinci_mdio_default {
    		pinctrl-single,pins = <
    			/* MDIO */
    			0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)	/* mdio_data.mdio_data */
    			0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0)			/* mdio_clk.mdio_clk */
    		>;
    	};
    
    	davinci_mdio_sleep: davinci_mdio_sleep {
    		pinctrl-single,pins = <
    			/* MDIO reset value */
    			0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7)
    			0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7)
    		>;
    	};
    
    	mmc1_pins: pinmux_mmc1_pins {
    		pinctrl-single,pins = <
    			0x160 (PIN_INPUT | MUX_MODE7) /* GPIO0_6 */
    		>;
    	};
    
    	emmc_pins: pinmux_emmc_pins {
    		pinctrl-single,pins = <
    			0x80 (PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn1.mmc1_clk */
    			0x84 (PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn2.mmc1_cmd */
    			0x00 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad0.mmc1_dat0 */
    			0x04 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad1.mmc1_dat1 */
    			0x08 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad2.mmc1_dat2 */
    			0x0c (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad3.mmc1_dat3 */
    			0x10 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad4.mmc1_dat4 */
    			0x14 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad5.mmc1_dat5 */
    			0x18 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad6.mmc1_dat6 */
    			0x1c (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad7.mmc1_dat7 */
    		>;
    	};
    };
    
    &uart0 {
    	pinctrl-names = "default";
    	pinctrl-0 = <&uart0_pins>;
    
    	status = "okay";
    };
    
    &usb {
    	status = "okay";
    };
    
    &usb_ctrl_mod {
    	status = "okay";
    };
    
    &usb0_phy {
    	status = "okay";
    };
    
    &usb1_phy {
    	status = "okay";
    };
    
    &usb0 {
    	status = "okay";
    	dr_mode = "peripheral";
    };
    
    &usb1 {
    	status = "okay";
    	dr_mode = "host";
    };
    
    &cppi41dma  {
    	status = "okay";
    };
    
    &i2c0 {
    	pinctrl-names = "default";
    	pinctrl-0 = <&i2c0_pins>;
    
    	status = "okay";
    	clock-frequency = <400000>;
    
    	tps: tps@24 {
    		reg = <0x24>;
    	};
    
    	baseboard_eeprom: baseboard_eeprom@50 {
    		compatible = "at,24c256";
    		reg = <0x50>;
    
    		#address-cells = <1>;
    		#size-cells = <1>;
    		baseboard_data: baseboard_data@0 {
    			reg = <0 0x100>;
    		};
    	};
    };
    
    &i2c2 {
    	pinctrl-names = "default";
    	pinctrl-0 = <&i2c2_pins>;
    
    	status = "okay";
    	clock-frequency = <100000>;
    
    	cape_eeprom0: cape_eeprom0@54 {
    		compatible = "at,24c256";
    		reg = <0x54>;
    		#address-cells = <1>;
    		#size-cells = <1>;
    		cape0_data: cape_data@0 {
    			reg = <0 0x100>;
    		};
    	};
    
    	cape_eeprom1: cape_eeprom1@55 {
    		compatible = "at,24c256";
    		reg = <0x55>;
    		#address-cells = <1>;
    		#size-cells = <1>;
    		cape1_data: cape_data@0 {
    			reg = <0 0x100>;
    		};
    	};
    
    	cape_eeprom2: cape_eeprom2@56 {
    		compatible = "at,24c256";
    		reg = <0x56>;
    		#address-cells = <1>;
    		#size-cells = <1>;
    		cape2_data: cape_data@0 {
    			reg = <0 0x100>;
    		};
    	};
    
    	cape_eeprom3: cape_eeprom3@57 {
    		compatible = "at,24c256";
    		reg = <0x57>;
    		#address-cells = <1>;
    		#size-cells = <1>;
    		cape3_data: cape_data@0 {
    			reg = <0 0x100>;
    		};
    	};
    };
    
    
    /include/ "tps65217.dtsi"
    
    &tps {
    	/*
    	 * Configure pmic to enter OFF-state instead of SLEEP-state ("RTC-only
    	 * mode") at poweroff.  Most BeagleBone versions do not support RTC-only
    	 * mode and risk hardware damage if this mode is entered.
    	 *
    	 * For details, see linux-omap mailing list May 2015 thread
    	 *	[PATCH] ARM: dts: am335x-bone* enable pmic-shutdown-controller
    	 * In particular, messages:
    	 *	http://www.spinics.net/lists/linux-omap/msg118585.html
    	 *	http://www.spinics.net/lists/linux-omap/msg118615.html
    	 *
    	 * You can override this later with
    	 *	&tps {  /delete-property/ ti,pmic-shutdown-controller;  }
    	 * if you want to use RTC-only mode and made sure you are not affected
    	 * by the hardware problems. (Tip: double-check by performing a current
    	 * measurement after shutdown: it should be less than 1 mA.)
    	 */
    /**	ti,pmic-shutdown-controller; */
    
    	regulators {
    		dcdc1_reg: regulator@0 {
    			regulator-name = "vdds_dpr";
    			regulator-always-on;
    		};
    
    		dcdc2_reg: regulator@1 {
    			/* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
    			regulator-name = "vdd_mpu";
    			regulator-min-microvolt = <925000>;
    			regulator-max-microvolt = <1351500>;
    			regulator-boot-on;
    			regulator-always-on;
    		};
    
    		dcdc3_reg: regulator@2 {
    			/* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
    			regulator-name = "vdd_core";
    			regulator-min-microvolt = <925000>;
    			regulator-max-microvolt = <1150000>;
    			regulator-boot-on;
    			regulator-always-on;
    		};
    
    		ldo1_reg: regulator@3 {
    			regulator-name = "vio,vrtc,vdds";
    			regulator-always-on;
    		};
    
    		ldo2_reg: regulator@4 {
    			regulator-name = "vdd_3v3aux";
    			regulator-always-on;
    		};
    
    		ldo3_reg: regulator@5 {
    			regulator-name = "vdd_1v8";
    			regulator-always-on;
    		};
    
    		ldo4_reg: regulator@6 {
    			regulator-name = "vdd_3v3a";
    			regulator-always-on;
    		};
    	};
    };
    
    &cpsw_emac0 {
    	phy_id = <&davinci_mdio>, <0>;
    	phy-mode = "mii";
    };
    
    &cpsw_emac1 {
    	phy_id = <&davinci_mdio>, <1>;
    	phy-mode = "mii";
    };
    
    &mac {
    	pinctrl-names = "default", "sleep";
    	pinctrl-0 = <&cpsw_default>;
    	pinctrl-1 = <&cpsw_sleep>;
    	status = "okay";
    };
    
    &davinci_mdio {
    	pinctrl-names = "default", "sleep";
    	pinctrl-0 = <&davinci_mdio_default>;
    	pinctrl-1 = <&davinci_mdio_sleep>;
    	status = "okay";
    };
    
    &mmc1 {
    	status = "okay";
    	bus-width = <0x4>;
    	pinctrl-names = "default";
    	pinctrl-0 = <&mmc1_pins>;
    	cd-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
    };
    
    &aes {
    	status = "okay";
    };
    
    &sham {
    	status = "okay";
    };
    
    &wkup_m3_ipc {
    	ti,scale-data-fw = "am335x-bone-scale-data.bin";
    };
    
    &rtc {
    	clocks = <&clk_32768_ck>, <&clkdiv32k_ick>;
    	clock-names = "ext-clk", "int-clk";
    	ti,system-power-controller;
    };
    
     
    /*
     * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
     *
     * 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.
     */
    /dts-v1/;
    
    #include "am33xx.dtsi"
    #include "am335x-bone-common.dtsi"
    #include <dt-bindings/display/tda998x.h>
    
    / {
    	model = "TI AM335x BeagleBone Black";
    	compatible = "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
    };
    
    &ldo3_reg {
    	regulator-min-microvolt = <1800000>;
    	regulator-max-microvolt = <1800000>;
    	regulator-always-on;
    };
    
    &mmc1 {
    	vmmc-supply = <&vmmcsd_fixed>;
    };
    
    &mmc2 {
    	vmmc-supply = <&vmmcsd_fixed>;
    	pinctrl-names = "default";
    	pinctrl-0 = <&emmc_pins>;
    	bus-width = <8>;
    	status = "okay";
    };
    
    &cpu0_opp_table {
    	/*
    	 * All PG 2.0 silicon may not support 1GHz but some of the early
    	 * BeagleBone Blacks have PG 2.0 silicon which is guaranteed
    	 * to support 1GHz OPP so enable it for PG 2.0 on this board.
    	 */
    	oppnitro@1000000000 {
    		opp-supported-hw = <0x06 0x0100>;
    	};
    };
    
    &am33xx_pinmux {
    	nxp_hdmi_bonelt_pins: nxp_hdmi_bonelt_pins {
    		pinctrl-single,pins = <
    			0x1b0 0x03      /* xdma_event_intr0, OMAP_MUX_MODE3 | AM33XX_PIN_OUTPUT */
    			0xa0 0x08       /* lcd_data0.lcd_data0, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
    			0xa4 0x08       /* lcd_data1.lcd_data1, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
    			0xa8 0x08       /* lcd_data2.lcd_data2, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
    			0xac 0x08       /* lcd_data3.lcd_data3, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
    			0xb0 0x08       /* lcd_data4.lcd_data4, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
    			0xb4 0x08       /* lcd_data5.lcd_data5, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
    			0xb8 0x08       /* lcd_data6.lcd_data6, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
    			0xbc 0x08       /* lcd_data7.lcd_data7, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
    			0xc0 0x08       /* lcd_data8.lcd_data8, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
    			0xc4 0x08       /* lcd_data9.lcd_data9, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
    			0xc8 0x08       /* lcd_data10.lcd_data10, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
    			0xcc 0x08       /* lcd_data11.lcd_data11, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
    			0xd0 0x08       /* lcd_data12.lcd_data12, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
    			0xd4 0x08       /* lcd_data13.lcd_data13, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
    			0xd8 0x08       /* lcd_data14.lcd_data14, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
    			0xdc 0x08       /* lcd_data15.lcd_data15, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
    			0xe0 0x00       /* lcd_vsync.lcd_vsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
    			0xe4 0x00       /* lcd_hsync.lcd_hsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
    			0xe8 0x00       /* lcd_pclk.lcd_pclk, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
    			0xec 0x00       /* lcd_ac_bias_en.lcd_ac_bias_en, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
    		>;
    	};
    	nxp_hdmi_bonelt_off_pins: nxp_hdmi_bonelt_off_pins {
    		pinctrl-single,pins = <
    			0x1b0 0x03      /* xdma_event_intr0, OMAP_MUX_MODE3 | AM33XX_PIN_OUTPUT */
    		>;
    	};
    
    	mcasp0_pins: mcasp0_pins {
    		pinctrl-single,pins = <
    			AM33XX_IOPAD(0x9ac, PIN_INPUT_PULLUP | MUX_MODE0) /* mcasp0_ahcklx.mcasp0_ahclkx */
    			AM33XX_IOPAD(0x99c, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mcasp0_ahclkr.mcasp0_axr2*/
    			AM33XX_IOPAD(0x994, PIN_OUTPUT_PULLUP | MUX_MODE0) /* mcasp0_fsx.mcasp0_fsx */
    			AM33XX_IOPAD(0x990, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mcasp0_aclkx.mcasp0_aclkx */
    			AM33XX_IOPAD(0x86c, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a11.GPIO1_27 */
    		>;
    	};
    };
    
    &lcdc {
    	status = "okay";
    	port {
    		lcdc_0: endpoint@0 {
    			remote-endpoint = <&hdmi_0>;
    		};
    	};
    };
    
    &i2c0 {
    	tda19988: tda19988 {
    		compatible = "nxp,tda998x";
    		reg = <0x70>;
    
    		pinctrl-names = "default", "off";
    		pinctrl-0 = <&nxp_hdmi_bonelt_pins>;
    		pinctrl-1 = <&nxp_hdmi_bonelt_off_pins>;
    
    		#sound-dai-cells = <0>;
    		audio-ports = <	AFMT_I2S	0x03>;
    
    		ports {
    			port@0 {
    				hdmi_0: endpoint@0 {
    					remote-endpoint = <&lcdc_0>;
    				};
    			};
    		};
    	};
    };
    
    &rtc {
    	system-power-controller;
    };
    
    &mcasp0	{
    	#sound-dai-cells = <0>;
    	pinctrl-names = "default";
    	pinctrl-0 = <&mcasp0_pins>;
    	status = "okay";
    	op-mode = <0>;	/* MCASP_IIS_MODE */
    	tdm-slots = <2>;
    	serial-dir = <	/* 0: INACTIVE, 1: TX, 2: RX */
    			0 0 1 0
    		>;
    	tx-num-evt = <32>;
    	rx-num-evt = <32>;
    };
    
    &sgx {
    	status = "okay";
    };
    
    / {
    	clk_mcasp0_fixed: clk_mcasp0_fixed {
    		#clock-cells = <0>;
    		compatible = "fixed-clock";
    		clock-frequency = <24576000>;
    	};
    
    	clk_mcasp0: clk_mcasp0 {
    		#clock-cells = <0>;
    		compatible = "gpio-gate-clock";
    		clocks = <&clk_mcasp0_fixed>;
    		enable-gpios = <&gpio1 27 0>; /* BeagleBone Black Clk enable on GPIO1_27 */
    	};
    
    	sound {
    		compatible = "simple-audio-card";
    		simple-audio-card,name = "TI BeagleBone Black";
    		simple-audio-card,format = "i2s";
    		simple-audio-card,bitclock-master = <&dailink0_master>;
    		simple-audio-card,frame-master = <&dailink0_master>;
    
    		dailink0_master: simple-audio-card,cpu {
    			sound-dai = <&mcasp0>;
    			clocks = <&clk_mcasp0>;
    		};
    
    		simple-audio-card,codec {
    			sound-dai = <&tda19988>;
    		};
    	};
    };
    

  • Hi, Mike,

    Did you read my last post?
    Do you have idea about 40 mA power supplying in RTC-only mode?

    Best regards,
    Oleg.