13 Replies Latest reply on Nov 9, 2012 11:52 AM by timsoft

    has anyone got a linux kernel driver for mcp79410 rtc  -solved

    timsoft

      I originally ordered a BQ320000DR from farnell to make a rtc module for my raspberrypi. there is a kernel driver for this rtc i2c chip.

      unfortunately, the chip still hasn't arrived, and in the mean-time I ordered a MCP79410-I/SN RTCC (i2c).

      I can see this on the i2c bus (address 6F) but there doesn't appear to be kernel drivers for this device (mcp7941x series)

      If there was another chip which was functionally the same, but with a kernel driver, I could just copy it's driver and change the chip name throughout the code.

       

      does anyone know of a i2c chip for which there is kernel support, which is similar to the mcp79410?

       

      I have the list of currently supported rtc chips (see drivers/rtc in the kernel source)

       

      88pm80x,88pm860x,ab3100,ab8500,at32ap700x,at91rm9200,at91sam9,au1xxx,bfin,bq32k,bq4802,cmos,coh901331,core,da9052,davinci,dev,dm355evm,

      ds1216,ds1286,ds1302,ds1305,ds1307,ds1374,ds1390,ds1511,ds1553,ds1672,ds1742,ds3232,ds3234,efi,em3027,ep93xx,fm3130,generic,imxdi,isl12022,

      isl1208,jz4740,lib,lpc32xx,ls1x,m41t80,m41t93,m41t94,m48t35,m48t59,m48t86,max6900,max6902,max8925,max8998,mc13xxx,mpc5121,mrst,msm6242,

      mv,mxc,nuc900,omap,pcap,pcf2123,pcf50633,pcf8563,pcf8583,pl030,pl031,pm8xxx,proc,ps3,puv3,pxa,r9701,rp5c01,rs5c313,rs5c348,rs5c372,rv3029c2,

      rx8025,rx8581,s35390a,s3c,sa1100,sh,spear,starfire,stk17ta8,stmp3xxx,sun4v,sysfs,tegra,test,tile,twl,tx4939,v3020,vr41xx,vt8500,wm831x,wm8350,x1205

       

      thanks

        • Re: has anyone got a linux kernel driver for mcp79410 rtc

          Hi Tim!

           

          You want the ds1307 driver, however it sort of depends which kernel you're running, the patch to add the mcp7941x series isn't in the 3.1.9+ kernel that's default in most of the current distros.  If you're ok with patching your kernel and re-compling it then you can find the patch here: http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=commitdiff;h=43fcb81550f7a16be192b19c77a379c9b27b1585 but be aware that it may not apply cleanly to the older kernel depending on what other changes there were.

           

          However the patch did make it into 3.2, so if you don't want to mess with kernel compiling then have a look at Chris Boots kernel http://www.bootc.net/projects/raspberry-pi-kernel/

           

          I'd also suggest asking Raspberry Pi questions over in the Raspberry Pi section http://www.element14.com/community/groups/raspberry-pi?ICID=technologies_rpi_menubar. There's a fair number of us over there willing to help, but we're not necessarily going to see stuff here in the Experts section.

            • Re: has anyone got a linux kernel driver for mcp79410 rtc
              timsoft

              thanks very much selsinork.

              My next challenge will be to get the 3.1.9 kernel source for my current armedslack install on my raspberrypi, as the source is not at kernel.org anymore;

              or, find out the config with special raspberrypi blobs and patches and see if I can get the 3.6rc1 kernel built instead. I'll post in the raspberry pi section in future, but there still seams to be a problem with posts dissapearing entirely on all the forums here at element14/farnell

                • Re: has anyone got a linux kernel driver for mcp79410 rtc

                  http://www.kernel.org/pub/linux/kernel/v3.x/linux-3.1.9.tar.gz still seems to be there..

                   

                  'official' 3.1.9 kernel source for the Pi is available here https://github.com/raspberrypi/linux and this will include all the necessary drivers.

                   

                  You're unlikely to get 3.6rc1 working, there are too many missing pieces and there's a lot of changes to arm code between 3.1.9 and 3.6 making forward porting it far from simple..

                  That said, if you're a wizard kernel developer then you should go look at  https://github.com/lp0/linux Simon Arlott and Chris Boot have done a bunch of work in this direction. You'll need this too https://github.com/raspberrypi/linux/wiki/Device-Tree-port and you probably want to sign up to the mailing list http://lists.infradead.org/mailman/listinfo/linux-rpi-kernel

                   

                  It appears that either an admin moved the thread into the Raspberry Pi area, or it magically disappeared only to turn up in the right place on it's own

                    • Re: has anyone got a linux kernel driver for mcp79410 rtc
                      timsoft

                      well I'm not a wizard kernel developer, I've compiled a few custom kernels for pc's but that's about it. Thanks for the pointer to the 3.1.9 kernel source. I should have hunted further on the site. I'l get that downloaded and see I can get the rtc module happy.

                        • Re: has anyone got a linux kernel driver for mcp79410 rtc
                          timsoft

                          just an update. I tried the patch on the kernel and it didn't like it, so I manually put in the changes roughly comparing them with the 3.6rc1. with modifying the include/linux/vermagic.h I can get the module to compile, but when I try insmod rtc-ds1307.ko it complains of an "-1 unknown symbol in module". the joys :-(

                            • Re: has anyone got a linux kernel driver for mcp79410 rtc
                              Drew Fustini

                              What version of the kernel were you modifying for those changes in 3.6rc1?  The Foundation's 3.1.9+?

                               

                              (btw, in case it's any help, I wrote this document awhile back http://www.element14.com/community/docs/DOC-44948/l/compiling-linux-kernel-staging-driver-modules)


                                • Re: has anyone got a linux kernel driver for mcp79410 rtc
                                  timsoft

                                  yes, the 3.1.9+ one from github/raspberrypi/linux, although it looks like it may now have moved up a subversion - see https://github.com/raspberrypi/linux/blob/rpi-3.2.27/Makefile

                                  I'll have a look at your kernel (cross) compiling guide drew, and try that. I think part of the problem is that my slackware distribution was using the 3.1.9 kernel, but still had 2.6.38.4 source present as well. (in /usr/src). I used david (spencer's) kernel+installer from http://www.daves-collective.co.uk/raspi/images/raspi-slack-installer_01Aug12.img.xz

                                   

                                  since this post slackware 14.0 (and armedslack 14.0 ) has come out. this updates the source framework to 3.4.11

                                  hopefully dave will update his kernel installer/package for slackware from the 3.1.9 version to a 3.2.x or higher, as I belive that is required to add the rtc device to the kernel using the method posted http://www.element14.com/community/groups/raspberry-pi/blog/2012/07/19/what-time-is-it-adding-a-rtc-to-the-raspberry-pi-via-i2c 

                                  I am looking forward to testing the little module I made to see if it works!

                                  • Re: has anyone got a linux kernel driver for mcp79410 rtc
                                    timsoft

                                    I've just updated to the 3.6.1 kernel,(with slackware 14.0) and have been able to compile the rtc-ds1703 kernel module.

                                    I can install it with modprobe, but don't know how to tell the module that the device is at 0x6f on the i2c-0 port (ie. mcp79410) instead of 0x68 (ds1307) .

                                    i have /dev/i2c-0 and /dev/i2c-1 and if i do a i2cdetect 0 -y it shows the device at 0x6f

                                    i have tried

                                    echo mcp7941x 0x6f > /sys/class/i2c-adapter/i2c-0/new_device

                                    but I just get "no such file or directory" which is not a suprise as /sys/class/i2c-adapter does not exist. /sys/class/i2c-dev does, but substituting (ie using echo mcp7941x 0x6f > /sys/class/i2c-dev/i2c-0/new_device  ) still complains with error

                                    -bash /sys/class/i2c-dev/i2c-0/new_device: No such file or directory

                                      • Re: has anyone got a linux kernel driver for mcp79410 rtc

                                        modprobe rtc-ds1307

                                        echo mcp7941x 0x6f > /sys/bus/i2c/devices/i2c-0/new_device

                                         

                                        works for me on a slightly older kernel.. I've not checked 3.6.1 (why can't they stick to mainline ?) but if /sys/class/i2c-adapter doesn't exist, it's possible you're missing some other stuff. Do you have i2c-dev compiled in or loaded as a module ?

                                         

                                        Based on my older kernel it appears you'd want to use /sys/class/i2c-dev/i2c-0/device/new_device if you use that path.

                                         

                                        Have you read Documentation/i2c/instantiating-devices in the kernel tree ?   There's a couple of ways in there to get the device configured, my personal choice is to use platform data (i.e. method 1) which also lets you configure the kernel to automatically set the clock on boot.

                                          • Re: has anyone got a linux kernel driver for mcp79410 rtc
                                            timsoft

                                            you hit the nail on the head, thanks. I just had a thought last night to look for "new_device" anywhere in the /sys/class/i2c-dev path and came up with the same location.

                                            so, once the rtc module is loaded with modprobe i2c:mcp7941x  (or insmod rtc_ds1307   )

                                             

                                            echo mcp7941x 0x6f > /sys/class/i2c-dev/i2c-0/device/new_device

                                             

                                            creates the /dev/rtc0 device, and after a bit of prodding*, hwclock -w set the time on the rtc, and hwclock -s can now be used in /etc/rc.d/rc.local to set the system time from the rtc (and hwclock -r shows the rtc time and date)

                                            *(to explain the prodding. initially after running above, I got ioctl errors when running hwclock. I then did

                                            cat /dev/rtc0

                                              (and ctl-c ), and that seemed to fix the problem. I could then set the rtc with hwclock -w   .the proper behaviour was preserved after a cold restart of the raspberrypi  )

                                             

                                            Info for other armedslack raspberrypi users

                                            you need to recompile the kernel and add rtc support. specifically

                                            CONFIG_RTC_LIB=y

                                            CONFIG_RTC_CLASS=y

                                            CONFIG_RTC_HCTOSYS=y

                                            CONFIG_RTC_HCTOSYS_DEVICE="rtc0"

                                            CONFIG_RTC_INTF_SYSFS=y

                                            CONFIG_RTC_INTF_PROC=y

                                            CONFIG_RTC_INTF_DEV=y

                                             

                                            CONFIG_RTC_DRV_DS1307=m

                                            I used the the kernel, modules and kernel source from http://ponce.cc/slackware/slackwarearm-14.0/raspi-slackbuild-3.6.y/  (thanks to ponce) as a starting point.

                                             

                                            then compile and install i2c-tools from slackbuilds.org (sbopkg). this gives the i2c-dev module, so you can "talk" to i2c bus and provides the i2cdetect and i2cdump and similar tools for

                                            probing the i2c busses.

                                             

                                            my /etc/rc.d/rc.local includes the following lines at the bottom

                                            modprobe i2c-dev

                                            modprobe i2c:mcp7941x

                                            echo mcp7941x 0x6f > /sys/class/i2c-dev/i2c-0/device/new_device

                                            hwclock -s

                                            Now I know my rtc gadget works, I'll have to find somewhere to post the circuit layouts for folks so they can make their own. The mcp79410 is quite a bit cheaper than the ds1307 and happens to run at 3.3v so you don't need any 5v-3.3v 2way buffering on the i2c bus. It also has battery backup function.

                                             

                                            thanks again for your assistance selsinork et-al

                                              • Re: has anyone got a linux kernel driver for mcp79410 rtc

                                                creates the /dev/rtc0 device, and after a bit of prodding*, hwclock -w set the time on the rtc, and hwclock -s can now be used in /etc/rc.d/rc.local to set the system time from the rtc (and hwclock -r shows the rtc time and date)

                                                *(to explain the prodding. initially after running above, I got ioctl errors when running hwclock. I then did

                                                There's a bit in one of the registers needs setting to start the oscillator running, probably you'll have problems until the oscilaltor is running and the initial date/time is set. Theoretically you only need to do it once - or at least until you loose both main power and battery.

                                                 

                                                I'd imagine you could do it properly with i2cset having read the datasheet to find the right bit.

                                                  • Re: has anyone got a linux kernel driver for mcp79410 rtc
                                                    timsoft

                                                    i've looked at the datasheet, and according to it, one should set the highest bit (bit7 if you start at bit0) to 1 to start the oscillator. because the ports are not symetrical (you read from control address 0x6f for the rtc registers, but write to 0x6e) you have to do things a little more manually. -update: following tests, it would appear that dispite what the datasheet says, you can only write using the same control address as the read address.

                                                    get byte from location 0 and i2c0 location 0x6f.

                                                    HEXVAL=`i2cdump -f -r 0-0 -y 0 0x6f b|tail -n1|awk '{printf("%#x\n",$2)}'`  

                                                    then or the value with 0x80 to turn on the oscillator bit

                                                     

                                                    NEWHEX=`echo $HEXVAL|awk '{printf("%#x\n", or($1,0x80)) }'`

                                                     

                                                    then write the new value back to the rtc . note: the rtc driver must be unloaded to sucessfully run i2cset on the rtc. even with -f it will not write unless you   rmmod rtc_ds1307

                                                    i2cset -f -y 0 0x6f 0 $NEWHEX

                                                     

                                                    you can now reload the driver  modprobe i2c:mcp7941x

                                                    and if it hasn't been configured, echo mcp7941x 0x6f > /sys/class/i2c-dev/i2c-0/device/new_device

                                                      • Re: has anyone got a linux kernel driver for mcp79410 rtc
                                                        timsoft

                                                        below is a sample script I wrote which does the turning on/off of the oscillator on the mcp79410 rtc usual disclaimer. it works for me. try it at your own peril. i release it public domain. it probably works on all sorts of distributions, but is only tested on slackware 14.0 with custom 3.6.1 kernel with rtc support compiled in and rtc-ds1307 compiled as a module. (and it requires i2c-tools to be installed, and i2c-dev module to be loaded.)

                                                         

                                                        #!/bin/sh
                                                        #this must be run as root.
                                                        if [ "`id -u`" != 0 ]; then
                                                          echo "this script must be run with root priviledges to access the hardware"
                                                          exit 1
                                                        fi
                                                        #and i2c-dev needs to be installed
                                                        if [ ! -e /usr/sbin/i2cdetect ]; then
                                                          echo "you must install i2c-tools package to be able to configure"
                                                          echo "devices on the i2c buses."
                                                          if [ -e /etc/slackware-version ]; then
                                                            echo "you can build a package using the slackbuild from www.slackbuilds.org"
                                                            echo "or by using sbopkg, or your method of choice"
                                                          fi
                                                          exit 1
                                                        fi
                                                        FORCEFLAG=""
                                                        if [ -e /dev/rtc0 ]; then
                                                          echo "warning. the kernel has already got the rtc driver loaded"
                                                          echo "you will need to unload it with   rmmod rtc_ds1307"
                                                          echo "then reload it with               modprobe i2c:mcp7941x"
                                                          echo "when you have set the oscillator."
                                                          exit 1
                                                        fi
                                                        #make sure we have a mcp7941x rtc present on the i2c bus
                                                        RTC_READ_PORT="0x6f"
                                                        #RTC_WRITE_PORT="0x6e"
                                                        #write port doesn't seem to work but you can write to the read port!
                                                        I2CBUS=""
                                                        if [ -e /dev/i2c-0 ]; then
                                                          #we have an i2c-0 bus so lets see if the rtc is here
                                                          ISRTC_HERE=`i2cdetect -y 0|grep "60:"|cut -c50|awk '($1!="--") {print "YES"}'`
                                                          if [ "$ISRTC_HERE" = "YES" ]; then
                                                            I2CBUS=0
                                                          fi
                                                        fi
                                                        if [ "$I2CBUS" = "" ]&&[ -e /dev/i2c-1 ]; then
                                                          #clock wasn't on i2c-0 but we have an i2c-1 so lets check it
                                                          ISRTC_HERE=`i2cdetect -y 1|grep "60:"|cut -c50|awk '($1!="--") {print "YES"}'`
                                                          if [ "$ISRTC_HERE" = "YES" ]; then
                                                            I2CBUS=1
                                                          fi
                                                        fi
                                                        if [ "$I2CBUS" = "" ]; then
                                                          echo "no mcp7941x rtc detected."
                                                          exit 1
                                                        fi
                                                        echo i2cbus is $I2CBUS
                                                        #now get the current seconds (bcd with oscillator control flag in top bit)
                                                        #and switch the oscillator bit on by or'ing the output with 0x80
                                                        HEXBYTE=`i2cdump $FORCEFLAG -r 0-0 -y $I2CBUS $RTC_READ_PORT b |tail -n1|awk '{print "0x" $2 }'`
                                                        echo "hexbyte is $HEXBYTE which is $(($HEXBYTE))"
                                                        
                                                        if [ `echo $(($HEXBYTE))` -lt 128 ]; then
                                                          echo "oscillator is not running"
                                                          NEWHEXBYTE=`echo $(($HEXBYTE))|awk '{oscon=or($1, 128);printf("%#x\n", oscon) }'`
                                                          echo "new hexbyte is $NEWHEXBYTE"
                                                          #now lets write the new value to the writable address for the rtc
                                                          #the writable address is the same as the read one, but with the 0 bit cleared
                                                          i2cset $FORCEFAG -y $I2CBUS $RTC_READ_PORT 0 $NEWHEXBYTE b
                                                          echo "started the oscillator"
                                                        else
                                                          echo "oscillator is already running"
                                                          echo "do you want to stop the oscillator y/n:"
                                                          read i
                                                          if [ "$i" = "y" ]||[ "$i" = "Y" ]; then
                                                            #remove top bit from byte
                                                            NEWHEXBYTE=`echo $((HEXBYTE))|awk '{oscoff=and($1,127);printf("%#x\n",oscoff) }'`
                                                            echo "new hexbyte is $NEWHEXBYTE"
                                                            i2cset $FORCEFLAG -y $I2CBUS $RTC_READ_PORT 0 $NEWHEXBYTE b
                                                            echo "stopped the oscillator"
                                                          fi
                                                        fi
                                                        

                                                        have fun :-)