xburst: remove 3.3 support
Signed-off-by: Gabor Juhos <juhosg@openwrt.org> SVN-Revision: 35934
This commit is contained in:
		| @@ -1,281 +0,0 @@ | |||||||
| CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y |  | ||||||
| CONFIG_ARCH_DISCARD_MEMBLOCK=y |  | ||||||
| CONFIG_ARCH_HIBERNATION_POSSIBLE=y |  | ||||||
| CONFIG_ARCH_REQUIRE_GPIOLIB=y |  | ||||||
| CONFIG_ARCH_SUSPEND_POSSIBLE=y |  | ||||||
| # CONFIG_ARPD is not set |  | ||||||
| CONFIG_BATTERY_JZ4740=y |  | ||||||
| # CONFIG_BLK_DEV_INITRD is not set |  | ||||||
| # CONFIG_BRIDGE is not set |  | ||||||
| CONFIG_CHARGER_GPIO=y |  | ||||||
| CONFIG_CONSOLE_TRANSLATIONS=y |  | ||||||
| CONFIG_CPU_HAS_PREFETCH=y |  | ||||||
| CONFIG_CPU_HAS_SYNC=y |  | ||||||
| CONFIG_CPU_LITTLE_ENDIAN=y |  | ||||||
| CONFIG_CPU_MIPS32=y |  | ||||||
| CONFIG_CPU_MIPS32_R1=y |  | ||||||
| CONFIG_CPU_MIPSR1=y |  | ||||||
| CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y |  | ||||||
| CONFIG_CPU_SUPPORTS_CPUFREQ=y |  | ||||||
| CONFIG_CPU_SUPPORTS_HIGHMEM=y |  | ||||||
| CONFIG_CRC16=y |  | ||||||
| CONFIG_CRYPTO_ALGAPI=y |  | ||||||
| CONFIG_CRYPTO_ALGAPI2=y |  | ||||||
| CONFIG_CRYPTO_DEFLATE=y |  | ||||||
| CONFIG_CRYPTO_LZO=y |  | ||||||
| CONFIG_CRYPTO_XZ=y |  | ||||||
| CONFIG_DEVMEM=y |  | ||||||
| CONFIG_DMA_NONCOHERENT=y |  | ||||||
| CONFIG_DUMMY_CONSOLE=y |  | ||||||
| CONFIG_EARLY_PRINTK=y |  | ||||||
| CONFIG_ELF_CORE=y |  | ||||||
| CONFIG_ENABLE_MUST_CHECK=y |  | ||||||
| CONFIG_EXT4_FS=y |  | ||||||
| CONFIG_FAT_FS=y |  | ||||||
| CONFIG_FB=y |  | ||||||
| CONFIG_FB_JZ4740=y |  | ||||||
| CONFIG_FB_SYS_COPYAREA=y |  | ||||||
| CONFIG_FB_SYS_FILLRECT=y |  | ||||||
| CONFIG_FB_SYS_IMAGEBLIT=y |  | ||||||
| # CONFIG_FB_WMT_GE_ROPS is not set |  | ||||||
| CONFIG_FONTS=y |  | ||||||
| # CONFIG_FONT_10x18 is not set |  | ||||||
| CONFIG_FONT_6x11=y |  | ||||||
| # CONFIG_FONT_7x14 is not set |  | ||||||
| # CONFIG_FONT_8x16 is not set |  | ||||||
| # CONFIG_FONT_8x8 is not set |  | ||||||
| # CONFIG_FONT_ACORN_8x8 is not set |  | ||||||
| # CONFIG_FONT_MINI_4x6 is not set |  | ||||||
| # CONFIG_FONT_PEARL_8x8 is not set |  | ||||||
| # CONFIG_FONT_SUN12x22 is not set |  | ||||||
| # CONFIG_FONT_SUN8x16 is not set |  | ||||||
| CONFIG_FORCE_MAX_ZONEORDER=12 |  | ||||||
| CONFIG_FRAMEBUFFER_CONSOLE=y |  | ||||||
| # CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set |  | ||||||
| # CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set |  | ||||||
| CONFIG_FREEZER=y |  | ||||||
| CONFIG_FS_MBCACHE=y |  | ||||||
| CONFIG_GENERIC_ATOMIC64=y |  | ||||||
| CONFIG_GENERIC_CLOCKEVENTS=y |  | ||||||
| CONFIG_GENERIC_CLOCKEVENTS_BUILD=y |  | ||||||
| CONFIG_GENERIC_CMOS_UPDATE=y |  | ||||||
| CONFIG_GENERIC_GPIO=y |  | ||||||
| CONFIG_GENERIC_IRQ_CHIP=y |  | ||||||
| CONFIG_GENERIC_IRQ_SHOW=y |  | ||||||
| CONFIG_GPIOLIB=y |  | ||||||
| # CONFIG_HAMRADIO is not set |  | ||||||
| CONFIG_HARDWARE_WATCHPOINTS=y |  | ||||||
| CONFIG_HAS_DMA=y |  | ||||||
| CONFIG_HAS_IOMEM=y |  | ||||||
| CONFIG_HAS_IOPORT=y |  | ||||||
| CONFIG_HAVE_ARCH_JUMP_LABEL=y |  | ||||||
| CONFIG_HAVE_ARCH_KGDB=y |  | ||||||
| CONFIG_HAVE_CLK=y |  | ||||||
| CONFIG_HAVE_C_RECORDMCOUNT=y |  | ||||||
| CONFIG_HAVE_DMA_API_DEBUG=y |  | ||||||
| CONFIG_HAVE_DMA_ATTRS=y |  | ||||||
| CONFIG_HAVE_DYNAMIC_FTRACE=y |  | ||||||
| CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y |  | ||||||
| CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y |  | ||||||
| CONFIG_HAVE_FUNCTION_TRACER=y |  | ||||||
| CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y |  | ||||||
| CONFIG_HAVE_GENERIC_DMA_COHERENT=y |  | ||||||
| CONFIG_HAVE_GENERIC_HARDIRQS=y |  | ||||||
| CONFIG_HAVE_IDE=y |  | ||||||
| CONFIG_HAVE_IRQ_WORK=y |  | ||||||
| CONFIG_HAVE_MEMBLOCK=y |  | ||||||
| CONFIG_HAVE_MEMBLOCK_NODE_MAP=y |  | ||||||
| CONFIG_HAVE_OPROFILE=y |  | ||||||
| CONFIG_HAVE_PERF_EVENTS=y |  | ||||||
| CONFIG_HAVE_PWM=y |  | ||||||
| # CONFIG_HIGH_RES_TIMERS is not set |  | ||||||
| CONFIG_HW_CONSOLE=y |  | ||||||
| CONFIG_I2C=y |  | ||||||
| CONFIG_I2C_BOARDINFO=y |  | ||||||
| # CONFIG_INLINE_READ_UNLOCK is not set |  | ||||||
| # CONFIG_INLINE_READ_UNLOCK_IRQ is not set |  | ||||||
| # CONFIG_INLINE_SPIN_UNLOCK is not set |  | ||||||
| # CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set |  | ||||||
| # CONFIG_INLINE_WRITE_UNLOCK is not set |  | ||||||
| # CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set |  | ||||||
| CONFIG_INPUT=y |  | ||||||
| CONFIG_INPUT_EVDEV=y |  | ||||||
| CONFIG_INPUT_KEYBOARD=y |  | ||||||
| CONFIG_INPUT_MOUSE=y |  | ||||||
| CONFIG_INPUT_MOUSEDEV=y |  | ||||||
| # CONFIG_INPUT_MOUSEDEV_PSAUX is not set |  | ||||||
| CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 |  | ||||||
| CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 |  | ||||||
| # CONFIG_INPUT_PWM_BEEPER is not set |  | ||||||
| CONFIG_INPUT_UINPUT=y |  | ||||||
| CONFIG_IRQ_CPU=y |  | ||||||
| CONFIG_IRQ_FORCED_THREADING=y |  | ||||||
| CONFIG_JBD2=y |  | ||||||
| CONFIG_JZ4740_QI_LB60=y |  | ||||||
| CONFIG_KALLSYMS=y |  | ||||||
| CONFIG_KEXEC=y |  | ||||||
| # CONFIG_KEYBOARD_GPIO is not set |  | ||||||
| CONFIG_LEGACY_PTYS=y |  | ||||||
| CONFIG_LEGACY_PTY_COUNT=2 |  | ||||||
| CONFIG_LZO_COMPRESS=y |  | ||||||
| CONFIG_LZO_DECOMPRESS=y |  | ||||||
| CONFIG_MACH_JZ4740=y |  | ||||||
| CONFIG_MFD_CORE=y |  | ||||||
| CONFIG_MFD_JZ4740_ADC=y |  | ||||||
| CONFIG_MIPS=y |  | ||||||
| CONFIG_MIPS_CPUFREQ=y |  | ||||||
| CONFIG_MIPS_FPU_EMU=y |  | ||||||
| CONFIG_MIPS_L1_CACHE_SHIFT=5 |  | ||||||
| # CONFIG_MIPS_MACHINE is not set |  | ||||||
| CONFIG_MIPS_MT_DISABLED=y |  | ||||||
| CONFIG_MMC=y |  | ||||||
| CONFIG_MMC_BLOCK=y |  | ||||||
| # CONFIG_MMC_BLOCK_BOUNCE is not set |  | ||||||
| CONFIG_MMC_JZ4740=y |  | ||||||
| CONFIG_MMC_UNSAFE_RESUME=y |  | ||||||
| # CONFIG_MOUSE_BCM5974 is not set |  | ||||||
| CONFIG_MOUSE_PS2=y |  | ||||||
| # CONFIG_MOUSE_PS2_ALPS is not set |  | ||||||
| # CONFIG_MOUSE_PS2_ELANTECH is not set |  | ||||||
| # CONFIG_MOUSE_PS2_LOGIPS2PP is not set |  | ||||||
| # CONFIG_MOUSE_PS2_SYNAPTICS is not set |  | ||||||
| # CONFIG_MOUSE_PS2_TOUCHKIT is not set |  | ||||||
| # CONFIG_MOUSE_PS2_TRACKPOINT is not set |  | ||||||
| # CONFIG_MOUSE_SERIAL is not set |  | ||||||
| # CONFIG_MOUSE_VSXXXAA is not set |  | ||||||
| # CONFIG_MTD_CFI is not set |  | ||||||
| # CONFIG_MTD_COMPLEX_MAPPINGS is not set |  | ||||||
| CONFIG_MTD_NAND=y |  | ||||||
| CONFIG_MTD_NAND_ECC=y |  | ||||||
| CONFIG_MTD_NAND_JZ4740=y |  | ||||||
| # CONFIG_MTD_SM_COMMON is not set |  | ||||||
| CONFIG_MTD_UBI=y |  | ||||||
| CONFIG_MTD_UBI_BEB_RESERVE=1 |  | ||||||
| # CONFIG_MTD_UBI_DEBUG is not set |  | ||||||
| # CONFIG_MTD_UBI_GLUEBI is not set |  | ||||||
| CONFIG_MTD_UBI_WL_THRESHOLD=4096 |  | ||||||
| CONFIG_NEED_DMA_MAP_STATE=y |  | ||||||
| CONFIG_NEED_PER_CPU_KM=y |  | ||||||
| # CONFIG_NETWORK_FILESYSTEMS is not set |  | ||||||
| # CONFIG_NET_SCHED is not set |  | ||||||
| # CONFIG_NEW_LEDS is not set |  | ||||||
| CONFIG_NLS=y |  | ||||||
| CONFIG_NLS_ASCII=y |  | ||||||
| CONFIG_NLS_CODEPAGE_1250=y |  | ||||||
| CONFIG_NLS_CODEPAGE_1251=y |  | ||||||
| CONFIG_NLS_CODEPAGE_437=y |  | ||||||
| CONFIG_NLS_CODEPAGE_737=y |  | ||||||
| CONFIG_NLS_CODEPAGE_775=y |  | ||||||
| CONFIG_NLS_CODEPAGE_850=y |  | ||||||
| CONFIG_NLS_CODEPAGE_852=y |  | ||||||
| CONFIG_NLS_CODEPAGE_855=y |  | ||||||
| CONFIG_NLS_CODEPAGE_857=y |  | ||||||
| CONFIG_NLS_CODEPAGE_860=y |  | ||||||
| CONFIG_NLS_CODEPAGE_861=y |  | ||||||
| CONFIG_NLS_CODEPAGE_862=y |  | ||||||
| CONFIG_NLS_CODEPAGE_863=y |  | ||||||
| CONFIG_NLS_CODEPAGE_864=y |  | ||||||
| CONFIG_NLS_CODEPAGE_865=y |  | ||||||
| CONFIG_NLS_CODEPAGE_866=y |  | ||||||
| CONFIG_NLS_CODEPAGE_869=y |  | ||||||
| CONFIG_NLS_CODEPAGE_874=y |  | ||||||
| CONFIG_NLS_CODEPAGE_932=y |  | ||||||
| CONFIG_NLS_CODEPAGE_936=y |  | ||||||
| CONFIG_NLS_CODEPAGE_949=y |  | ||||||
| CONFIG_NLS_CODEPAGE_950=y |  | ||||||
| CONFIG_NLS_ISO8859_1=y |  | ||||||
| CONFIG_NLS_ISO8859_13=y |  | ||||||
| CONFIG_NLS_ISO8859_14=y |  | ||||||
| CONFIG_NLS_ISO8859_15=y |  | ||||||
| CONFIG_NLS_ISO8859_2=y |  | ||||||
| CONFIG_NLS_ISO8859_3=y |  | ||||||
| CONFIG_NLS_ISO8859_4=y |  | ||||||
| CONFIG_NLS_ISO8859_5=y |  | ||||||
| CONFIG_NLS_ISO8859_6=y |  | ||||||
| CONFIG_NLS_ISO8859_7=y |  | ||||||
| CONFIG_NLS_ISO8859_8=y |  | ||||||
| CONFIG_NLS_ISO8859_9=y |  | ||||||
| CONFIG_NLS_KOI8_R=y |  | ||||||
| CONFIG_NLS_KOI8_U=y |  | ||||||
| CONFIG_NLS_UTF8=y |  | ||||||
| CONFIG_PAGEFLAGS_EXTENDED=y |  | ||||||
| # CONFIG_PDA_POWER is not set |  | ||||||
| CONFIG_PERF_USE_VMALLOC=y |  | ||||||
| CONFIG_PM=y |  | ||||||
| CONFIG_PM_CLK=y |  | ||||||
| # CONFIG_PM_DEBUG is not set |  | ||||||
| CONFIG_PM_SLEEP=y |  | ||||||
| CONFIG_POWER_SUPPLY=y |  | ||||||
| CONFIG_PREEMPT=y |  | ||||||
| CONFIG_PREEMPT_COUNT=y |  | ||||||
| # CONFIG_PREEMPT_NONE is not set |  | ||||||
| CONFIG_PREEMPT_RCU=y |  | ||||||
| CONFIG_PRINTK_TIME=y |  | ||||||
| CONFIG_PROC_PAGE_MONITOR=y |  | ||||||
| # CONFIG_RCU_BOOST is not set |  | ||||||
| CONFIG_REGMAP=y |  | ||||||
| CONFIG_REGMAP_I2C=y |  | ||||||
| CONFIG_RTC_CLASS=y |  | ||||||
| # CONFIG_RTC_DRV_CMOS is not set |  | ||||||
| CONFIG_RTC_DRV_JZ4740=y |  | ||||||
| # CONFIG_SCSI_DMA is not set |  | ||||||
| # CONFIG_SENSORS_JZ4740 is not set |  | ||||||
| CONFIG_SERIO=y |  | ||||||
| CONFIG_SERIO_LIBPS2=y |  | ||||||
| CONFIG_SND=y |  | ||||||
| # CONFIG_SND_EMU10K1_SEQ is not set |  | ||||||
| CONFIG_SND_JACK=y |  | ||||||
| CONFIG_SND_JZ4740_SOC=y |  | ||||||
| CONFIG_SND_JZ4740_SOC_I2S=y |  | ||||||
| CONFIG_SND_JZ4740_SOC_QI_LB60=y |  | ||||||
| # CONFIG_SND_OPL3_LIB_SEQ is not set |  | ||||||
| # CONFIG_SND_OPL4_LIB_SEQ is not set |  | ||||||
| CONFIG_SND_PCM=y |  | ||||||
| # CONFIG_SND_RAWMIDI_SEQ is not set |  | ||||||
| # CONFIG_SND_SBAWE_SEQ is not set |  | ||||||
| CONFIG_SND_SOC=y |  | ||||||
| # CONFIG_SND_SOC_ALL_CODECS is not set |  | ||||||
| CONFIG_SND_SOC_I2C_AND_SPI=y |  | ||||||
| CONFIG_SND_SOC_JZ4740_CODEC=y |  | ||||||
| CONFIG_SND_TIMER=y |  | ||||||
| CONFIG_SOUND=y |  | ||||||
| # CONFIG_SOUND_OSS_CORE is not set |  | ||||||
| # CONFIG_SQUASHFS is not set |  | ||||||
| # CONFIG_STAGING is not set |  | ||||||
| CONFIG_SUSPEND=y |  | ||||||
| CONFIG_SUSPEND_FREEZER=y |  | ||||||
| # CONFIG_SYN_COOKIES is not set |  | ||||||
| CONFIG_SYS_HAS_CPU_MIPS32_R1=y |  | ||||||
| CONFIG_SYS_HAS_EARLY_PRINTK=y |  | ||||||
| CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y |  | ||||||
| CONFIG_SYS_SUPPORTS_ARBIT_HZ=y |  | ||||||
| CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y |  | ||||||
| CONFIG_TINY_PREEMPT_RCU=y |  | ||||||
| CONFIG_UBIFS_FS=y |  | ||||||
| CONFIG_UBIFS_FS_ADVANCED_COMPR=y |  | ||||||
| # CONFIG_UBIFS_FS_DEBUG is not set |  | ||||||
| CONFIG_UBIFS_FS_LZO=y |  | ||||||
| # CONFIG_UBIFS_FS_XATTR is not set |  | ||||||
| CONFIG_UBIFS_FS_XZ=y |  | ||||||
| CONFIG_UBIFS_FS_ZLIB=y |  | ||||||
| # CONFIG_USB_ARCH_HAS_EHCI is not set |  | ||||||
| # CONFIG_USB_ARCH_HAS_XHCI is not set |  | ||||||
| # CONFIG_USB_AUDIO is not set |  | ||||||
| CONFIG_USB_COMMON=y |  | ||||||
| CONFIG_USB_ETH=y |  | ||||||
| # CONFIG_USB_ETH_EEM is not set |  | ||||||
| # CONFIG_USB_ETH_RNDIS is not set |  | ||||||
| CONFIG_USB_FUSB300=y |  | ||||||
| CONFIG_USB_GADGET=y |  | ||||||
| CONFIG_USB_GADGET_DUALSPEED=y |  | ||||||
| # CONFIG_USB_JZ4740 is not set |  | ||||||
| CONFIG_USB_SUPPORT=y |  | ||||||
| CONFIG_VFAT_FS=y |  | ||||||
| # CONFIG_VGA_CONSOLE is not set |  | ||||||
| # CONFIG_VLAN_8021Q is not set |  | ||||||
| CONFIG_VT=y |  | ||||||
| CONFIG_VT_CONSOLE=y |  | ||||||
| CONFIG_VT_CONSOLE_SLEEP=y |  | ||||||
| CONFIG_VT_HW_CONSOLE_BINDING=y |  | ||||||
| # CONFIG_WATCHDOG is not set |  | ||||||
| CONFIG_ZONE_DMA_FLAG=0 |  | ||||||
| @@ -1,52 +0,0 @@ | |||||||
| # CONFIG_BACKLIGHT_ADP8860 is not set |  | ||||||
| # CONFIG_BACKLIGHT_ADP8870 is not set |  | ||||||
| CONFIG_BACKLIGHT_CLASS_DEVICE=y |  | ||||||
| CONFIG_BACKLIGHT_GENERIC=y |  | ||||||
| CONFIG_BACKLIGHT_LCD_SUPPORT=y |  | ||||||
| CONFIG_BACKLIGHT_PWM=y |  | ||||||
| CONFIG_BLK_DEV_SD=y |  | ||||||
| CONFIG_GPIO_SYSFS=y |  | ||||||
| CONFIG_INPUT_PWM_BEEPER=y |  | ||||||
| CONFIG_INPUT_TOUCHSCREEN=y |  | ||||||
| CONFIG_KEYBOARD_GPIO=y |  | ||||||
| CONFIG_KEYBOARD_MATRIX=y |  | ||||||
| # CONFIG_LCD_AMS369FG06 is not set |  | ||||||
| CONFIG_LCD_CLASS_DEVICE=y |  | ||||||
| CONFIG_LCD_ILI8960=y |  | ||||||
| # CONFIG_LCD_L4F00242T03 is not set |  | ||||||
| # CONFIG_LCD_LD9040 is not set |  | ||||||
| # CONFIG_LCD_LMS283GF05 is not set |  | ||||||
| # CONFIG_LCD_LTV350QV is not set |  | ||||||
| # CONFIG_LCD_PLATFORM is not set |  | ||||||
| # CONFIG_LCD_S6E63M0 is not set |  | ||||||
| # CONFIG_LCD_TDO24M is not set |  | ||||||
| # CONFIG_LCD_VGG2432A4 is not set |  | ||||||
| CONFIG_LOGO=y |  | ||||||
| CONFIG_LOGO_LINUX_CLUT224=y |  | ||||||
| CONFIG_LOGO_LINUX_MONO=y |  | ||||||
| CONFIG_LOGO_LINUX_VGA16=y |  | ||||||
| CONFIG_REGMAP_SPI=y |  | ||||||
| CONFIG_SCSI=y |  | ||||||
| CONFIG_SCSI_DMA=y |  | ||||||
| CONFIG_SPI=y |  | ||||||
| CONFIG_SPI_BITBANG=y |  | ||||||
| CONFIG_SPI_GPIO=y |  | ||||||
| CONFIG_SPI_MASTER=y |  | ||||||
| # CONFIG_TOUCHSCREEN_ATMEL_MXT is not set |  | ||||||
| # CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set |  | ||||||
| # CONFIG_TOUCHSCREEN_BU21013 is not set |  | ||||||
| # CONFIG_TOUCHSCREEN_DYNAPRO is not set |  | ||||||
| # CONFIG_TOUCHSCREEN_EGALAX is not set |  | ||||||
| # CONFIG_TOUCHSCREEN_HAMPSHIRE is not set |  | ||||||
| # CONFIG_TOUCHSCREEN_MAX11801 is not set |  | ||||||
| # CONFIG_TOUCHSCREEN_PIXCIR is not set |  | ||||||
| # CONFIG_TOUCHSCREEN_ST1232 is not set |  | ||||||
| # CONFIG_TOUCHSCREEN_TSC2005 is not set |  | ||||||
| # CONFIG_TOUCHSCREEN_TSC_SERIO is not set |  | ||||||
| CONFIG_USB=y |  | ||||||
| # CONFIG_USB_DUMMY_HCD is not set |  | ||||||
| # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set |  | ||||||
| # CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set |  | ||||||
| CONFIG_USB_OHCI_HCD=y |  | ||||||
| # CONFIG_USB_OHCI_HCD_PLATFORM is not set |  | ||||||
| CONFIG_USB_STORAGE=y |  | ||||||
| @@ -1,11 +0,0 @@ | |||||||
| CONFIG_FB_DEFERRED_IO=y |  | ||||||
| CONFIG_FB_METRONOME=m |  | ||||||
| CONFIG_FB_SYS_FOPS=m |  | ||||||
| CONFIG_HWMON=y |  | ||||||
| CONFIG_I2C_ALGOBIT=y |  | ||||||
| CONFIG_LEDS_GPIO=y |  | ||||||
| # CONFIG_LEDS_PWM is not set |  | ||||||
| CONFIG_MTD_CMDLINE_PARTS=y |  | ||||||
| CONFIG_NEW_LEDS=y |  | ||||||
| # CONFIG_SENSORS_JZ4740 is not set |  | ||||||
| CONFIG_SENSORS_LM75=y |  | ||||||
| @@ -1 +0,0 @@ | |||||||
| CONFIG_I2C_ALGOBIT=y |  | ||||||
| @@ -1,21 +0,0 @@ | |||||||
| From 73aab29ddc44a3e1a7156473ad5bc9cd80704274 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Lars-Peter Clausen <lars@metafoo.de> |  | ||||||
| Date: Tue, 15 Mar 2011 12:49:15 +0100 |  | ||||||
| Subject: [PATCH 01/21] ubi: Read only the vid header instead of the whole |  | ||||||
|  page |  | ||||||
|  |  | ||||||
| --- |  | ||||||
|  drivers/mtd/ubi/io.c |    2 +- |  | ||||||
|  1 files changed, 1 insertions(+), 1 deletions(-) |  | ||||||
|  |  | ||||||
| --- a/drivers/mtd/ubi/io.c |  | ||||||
| +++ b/drivers/mtd/ubi/io.c |  | ||||||
| @@ -1030,7 +1030,7 @@ int ubi_io_read_vid_hdr(struct ubi_devic |  | ||||||
|   |  | ||||||
|  	p = (char *)vid_hdr - ubi->vid_hdr_shift; |  | ||||||
|  	read_err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset, |  | ||||||
| -			  ubi->vid_hdr_alsize); |  | ||||||
| +			  UBI_VID_HDR_SIZE + ubi->vid_hdr_shift); |  | ||||||
|  	if (read_err && read_err != UBI_IO_BITFLIPS && !mtd_is_eccerr(read_err)) |  | ||||||
|  		return read_err; |  | ||||||
|   |  | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,40 +0,0 @@ | |||||||
| From b971c50dc50c07f981a1619f977e7509db9c4eac Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Lars-Peter Clausen <lars@metafoo.de> |  | ||||||
| Date: Sat, 26 Feb 2011 15:30:07 +0100 |  | ||||||
| Subject: [PATCH 03/21] NAND: Optimize NAND_ECC_HW_OOB_FIRST read |  | ||||||
|  |  | ||||||
| Avoid sending unnecessary READ commands to the chip. |  | ||||||
| --- |  | ||||||
|  drivers/mtd/nand/nand_base.c |   14 ++++++++++---- |  | ||||||
|  1 files changed, 10 insertions(+), 4 deletions(-) |  | ||||||
|  |  | ||||||
| --- a/drivers/mtd/nand/nand_base.c |  | ||||||
| +++ b/drivers/mtd/nand/nand_base.c |  | ||||||
| @@ -1294,9 +1294,15 @@ static int nand_read_page_hwecc_oob_firs |  | ||||||
|  	uint8_t *ecc_calc = chip->buffers->ecccalc; |  | ||||||
|   |  | ||||||
|  	/* Read the OOB area first */ |  | ||||||
| -	chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); |  | ||||||
| -	chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); |  | ||||||
| -	chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page); |  | ||||||
| +	if (mtd->writesize > 512) { |  | ||||||
| +		chip->cmdfunc(mtd, NAND_CMD_READ0, mtd->writesize, page); |  | ||||||
| +		chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); |  | ||||||
| +		chip->cmdfunc(mtd, NAND_CMD_RNDOUT, 0, -1); |  | ||||||
| +	} else { |  | ||||||
| +		chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); |  | ||||||
| +		chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); |  | ||||||
| +		chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page); |  | ||||||
| +	} |  | ||||||
|   |  | ||||||
|  	for (i = 0; i < chip->ecc.total; i++) |  | ||||||
|  		ecc_code[i] = chip->oob_poi[eccpos[i]]; |  | ||||||
| @@ -1465,7 +1471,7 @@ static int nand_do_read_ops(struct mtd_i |  | ||||||
|  		if (realpage != chip->pagebuf || oob) { |  | ||||||
|  			bufpoi = aligned ? buf : chip->buffers->databuf; |  | ||||||
|   |  | ||||||
| -			if (likely(sndcmd)) { |  | ||||||
| +			if (likely(sndcmd) && chip->ecc.mode != NAND_ECC_HW_OOB_FIRST) { |  | ||||||
|  				chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); |  | ||||||
|  				sndcmd = 0; |  | ||||||
|  			} |  | ||||||
| @@ -1,144 +0,0 @@ | |||||||
| From 297d8a7bdfb755778d4189ca2861dd2a6125e972 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Lars-Peter Clausen <lars@metafoo.de> |  | ||||||
| Date: Tue, 15 Mar 2011 12:33:41 +0100 |  | ||||||
| Subject: [PATCH 04/21] NAND: Add support for subpage reads for |  | ||||||
|  NAND_ECC_HW_OOB_FIRST |  | ||||||
|  |  | ||||||
| --- |  | ||||||
|  drivers/mtd/nand/nand_base.c |   78 ++++++++++++++++++++++++++++++++++++++++-- |  | ||||||
|  include/linux/mtd/nand.h     |    8 ++-- |  | ||||||
|  2 files changed, 79 insertions(+), 7 deletions(-) |  | ||||||
|  |  | ||||||
| --- a/drivers/mtd/nand/nand_base.c |  | ||||||
| +++ b/drivers/mtd/nand/nand_base.c |  | ||||||
| @@ -1143,7 +1143,7 @@ static int nand_read_page_swecc(struct m |  | ||||||
|   * @bufpoi: buffer to store read data |  | ||||||
|   */ |  | ||||||
|  static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, |  | ||||||
| -			uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi) |  | ||||||
| +			uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi, int page) |  | ||||||
|  { |  | ||||||
|  	int start_step, end_step, num_steps; |  | ||||||
|  	uint32_t *eccpos = chip->ecc.layout->eccpos; |  | ||||||
| @@ -1324,6 +1324,75 @@ static int nand_read_page_hwecc_oob_firs |  | ||||||
|  } |  | ||||||
|   |  | ||||||
|  /** |  | ||||||
| + * nand_read_subpage_hwecc_oob_first - [REPLACABLE] hw ecc based sub-page read function |  | ||||||
| + * @mtd:	mtd info structure |  | ||||||
| + * @chip:	nand chip info structure |  | ||||||
| + * @data_offs:	offset of requested data within the page |  | ||||||
| + * @readlen:	data length |  | ||||||
| + * @bufpoi:	buffer to store read data |  | ||||||
| + * @page:	page number to read |  | ||||||
| + * |  | ||||||
| + * Hardware ECC for large page chips, require OOB to be read first. |  | ||||||
| + * For this ECC mode, the write_page method is re-used from ECC_HW. |  | ||||||
| + * These methods read/write ECC from the OOB area, unlike the |  | ||||||
| + * ECC_HW_SYNDROME support with multiple ECC steps, follows the |  | ||||||
| + * "infix ECC" scheme and reads/writes ECC from the data area, by |  | ||||||
| + * overwriting the NAND manufacturer bad block markings. |  | ||||||
| + */ |  | ||||||
| +static int nand_read_subpage_hwecc_oob_first(struct mtd_info *mtd, struct nand_chip *chip, |  | ||||||
| +			uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi, int page) |  | ||||||
| +{ |  | ||||||
| +	int start_step, end_step, num_steps; |  | ||||||
| +	uint32_t *eccpos = chip->ecc.layout->eccpos; |  | ||||||
| +	uint8_t *p; |  | ||||||
| +	int data_col_addr; |  | ||||||
| +	int eccsize = chip->ecc.size; |  | ||||||
| +	int eccbytes = chip->ecc.bytes; |  | ||||||
| +	uint8_t *ecc_code = chip->buffers->ecccode; |  | ||||||
| +	uint8_t *ecc_calc = chip->buffers->ecccalc; |  | ||||||
| +	int i; |  | ||||||
| + |  | ||||||
| +	/* Column address wihin the page aligned to ECC size */ |  | ||||||
| +	start_step = data_offs / chip->ecc.size; |  | ||||||
| +	end_step = (data_offs + readlen - 1) / chip->ecc.size; |  | ||||||
| +	num_steps = end_step - start_step + 1; |  | ||||||
| + |  | ||||||
| +	data_col_addr = start_step * chip->ecc.size; |  | ||||||
| + |  | ||||||
| +	/* Read the OOB area first */ |  | ||||||
| +	if (mtd->writesize > 512) { |  | ||||||
| +		chip->cmdfunc(mtd, NAND_CMD_READ0, mtd->writesize, page); |  | ||||||
| +		chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); |  | ||||||
| +		chip->cmdfunc(mtd, NAND_CMD_RNDOUT, data_col_addr, -1); |  | ||||||
| +	} else { |  | ||||||
| +		chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); |  | ||||||
| +		chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); |  | ||||||
| +		chip->cmdfunc(mtd, NAND_CMD_READ0, data_col_addr, page); |  | ||||||
| +	} |  | ||||||
| + |  | ||||||
| +	for (i = 0; i < chip->ecc.total; i++) |  | ||||||
| +		ecc_code[i] = chip->oob_poi[eccpos[i]]; |  | ||||||
| + |  | ||||||
| +	p = bufpoi + data_col_addr; |  | ||||||
| + |  | ||||||
| +	for (i = eccbytes * start_step; num_steps; num_steps--, i += eccbytes, p += eccsize) { |  | ||||||
| +		int stat; |  | ||||||
| + |  | ||||||
| +		chip->ecc.hwctl(mtd, NAND_ECC_READ); |  | ||||||
| +		chip->read_buf(mtd, p, eccsize); |  | ||||||
| +		chip->ecc.calculate(mtd, p, &ecc_calc[i]); |  | ||||||
| + |  | ||||||
| +		stat = chip->ecc.correct(mtd, p, &ecc_code[i], NULL); |  | ||||||
| +		if (stat < 0) |  | ||||||
| +			mtd->ecc_stats.failed++; |  | ||||||
| +		else |  | ||||||
| +			mtd->ecc_stats.corrected += stat; |  | ||||||
| +	} |  | ||||||
| + |  | ||||||
| +	return 0; |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +/** |  | ||||||
|   * nand_read_page_syndrome - [REPLACEABLE] hardware ECC syndrome based page read |  | ||||||
|   * @mtd: mtd info structure |  | ||||||
|   * @chip: nand chip info structure |  | ||||||
| @@ -1482,7 +1551,7 @@ static int nand_do_read_ops(struct mtd_i |  | ||||||
|  							      bufpoi, page); |  | ||||||
|  			else if (!aligned && NAND_SUBPAGE_READ(chip) && !oob) |  | ||||||
|  				ret = chip->ecc.read_subpage(mtd, chip, |  | ||||||
| -							col, bytes, bufpoi); |  | ||||||
| +							col, bytes, bufpoi, page); |  | ||||||
|  			else |  | ||||||
|  				ret = chip->ecc.read_page(mtd, chip, bufpoi, |  | ||||||
|  							  page); |  | ||||||
| @@ -3293,8 +3362,11 @@ int nand_scan_tail(struct mtd_info *mtd) |  | ||||||
|  				   "hardware ECC not possible\n"); |  | ||||||
|  			BUG(); |  | ||||||
|  		} |  | ||||||
| -		if (!chip->ecc.read_page) |  | ||||||
| +		if (!chip->ecc.read_page) { |  | ||||||
|  			chip->ecc.read_page = nand_read_page_hwecc_oob_first; |  | ||||||
| +			if (!chip->ecc.read_subpage) |  | ||||||
| +				chip->ecc.read_subpage = nand_read_subpage_hwecc_oob_first; |  | ||||||
| +		} |  | ||||||
|   |  | ||||||
|  	case NAND_ECC_HW: |  | ||||||
|  		/* Use standard hwecc read page function? */ |  | ||||||
| --- a/include/linux/mtd/nand.h |  | ||||||
| +++ b/include/linux/mtd/nand.h |  | ||||||
| @@ -211,9 +211,9 @@ typedef enum { |  | ||||||
|  #define NAND_MUST_PAD(chip) (!(chip->options & NAND_NO_PADDING)) |  | ||||||
|  #define NAND_HAS_CACHEPROG(chip) ((chip->options & NAND_CACHEPRG)) |  | ||||||
|  #define NAND_HAS_COPYBACK(chip) ((chip->options & NAND_COPYBACK)) |  | ||||||
| -/* Large page NAND with SOFT_ECC should support subpage reads */ |  | ||||||
| -#define NAND_SUBPAGE_READ(chip) ((chip->ecc.mode == NAND_ECC_SOFT) \ |  | ||||||
| -					&& (chip->page_shift > 9)) |  | ||||||
| +/* Large page NAND with read_subpage set should support subpage reads */ |  | ||||||
| +#define NAND_SUBPAGE_READ(chip) (((chip)->ecc.read_subpage) \ |  | ||||||
| +					&& ((chip)->page_shift > 9)) |  | ||||||
|   |  | ||||||
|  /* Mask to zero out the chip options, which come from the id table */ |  | ||||||
|  #define NAND_CHIPOPTIONS_MSK	(0x0000ffff & ~NAND_NO_AUTOINCR) |  | ||||||
| @@ -367,7 +367,7 @@ struct nand_ecc_ctrl { |  | ||||||
|  	int (*read_page)(struct mtd_info *mtd, struct nand_chip *chip, |  | ||||||
|  			uint8_t *buf, int page); |  | ||||||
|  	int (*read_subpage)(struct mtd_info *mtd, struct nand_chip *chip, |  | ||||||
| -			uint32_t offs, uint32_t len, uint8_t *buf); |  | ||||||
| +			uint32_t offs, uint32_t len, uint8_t *buf, int page); |  | ||||||
|  	void (*write_page)(struct mtd_info *mtd, struct nand_chip *chip, |  | ||||||
|  			const uint8_t *buf); |  | ||||||
|  	int (*write_oob_raw)(struct mtd_info *mtd, struct nand_chip *chip, |  | ||||||
| @@ -1,53 +0,0 @@ | |||||||
| From 4f28237a750afd1112b6f1266d36f8b718efe89c Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Xiangfu Liu <xiangfu@sharism.cc> |  | ||||||
| Date: Tue, 6 Mar 2012 11:19:26 +0800 |  | ||||||
| Subject: [PATCH 05/21] NAND-Optimize-reading-the-eec-data-for-the-JZ4740 |  | ||||||
|  |  | ||||||
| --- |  | ||||||
|  drivers/mtd/nand/nand_base.c |   14 ++++---------- |  | ||||||
|  1 files changed, 4 insertions(+), 10 deletions(-) |  | ||||||
|  |  | ||||||
| --- a/drivers/mtd/nand/nand_base.c |  | ||||||
| +++ b/drivers/mtd/nand/nand_base.c |  | ||||||
| @@ -1295,8 +1295,8 @@ static int nand_read_page_hwecc_oob_firs |  | ||||||
|   |  | ||||||
|  	/* Read the OOB area first */ |  | ||||||
|  	if (mtd->writesize > 512) { |  | ||||||
| -		chip->cmdfunc(mtd, NAND_CMD_READ0, mtd->writesize, page); |  | ||||||
| -		chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); |  | ||||||
| +		chip->cmdfunc(mtd, NAND_CMD_READ0, mtd->writesize + eccpos[0], page); |  | ||||||
| +		chip->read_buf(mtd, ecc_code, chip->ecc.total); |  | ||||||
|  		chip->cmdfunc(mtd, NAND_CMD_RNDOUT, 0, -1); |  | ||||||
|  	} else { |  | ||||||
|  		chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); |  | ||||||
| @@ -1304,9 +1304,6 @@ static int nand_read_page_hwecc_oob_firs |  | ||||||
|  		chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page); |  | ||||||
|  	} |  | ||||||
|   |  | ||||||
| -	for (i = 0; i < chip->ecc.total; i++) |  | ||||||
| -		ecc_code[i] = chip->oob_poi[eccpos[i]]; |  | ||||||
| - |  | ||||||
|  	for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { |  | ||||||
|  		int stat; |  | ||||||
|   |  | ||||||
| @@ -1361,8 +1358,8 @@ static int nand_read_subpage_hwecc_oob_f |  | ||||||
|   |  | ||||||
|  	/* Read the OOB area first */ |  | ||||||
|  	if (mtd->writesize > 512) { |  | ||||||
| -		chip->cmdfunc(mtd, NAND_CMD_READ0, mtd->writesize, page); |  | ||||||
| -		chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); |  | ||||||
| +		chip->cmdfunc(mtd, NAND_CMD_READ0, mtd->writesize + eccpos[0], page); |  | ||||||
| +		chip->read_buf(mtd, ecc_code, chip->ecc.total); |  | ||||||
|  		chip->cmdfunc(mtd, NAND_CMD_RNDOUT, data_col_addr, -1); |  | ||||||
|  	} else { |  | ||||||
|  		chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); |  | ||||||
| @@ -1370,9 +1367,6 @@ static int nand_read_subpage_hwecc_oob_f |  | ||||||
|  		chip->cmdfunc(mtd, NAND_CMD_READ0, data_col_addr, page); |  | ||||||
|  	} |  | ||||||
|   |  | ||||||
| -	for (i = 0; i < chip->ecc.total; i++) |  | ||||||
| -		ecc_code[i] = chip->oob_poi[eccpos[i]]; |  | ||||||
| - |  | ||||||
|  	p = bufpoi + data_col_addr; |  | ||||||
|   |  | ||||||
|  	for (i = eccbytes * start_step; num_steps; num_steps--, i += eccbytes, p += eccsize) { |  | ||||||
| @@ -1,417 +0,0 @@ | |||||||
| From d5814bdb661d3dac61422f8f69e459be884c9a9d Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Maarten ter Huurne <maarten@treewalker.org> |  | ||||||
| Date: Tue, 2 Aug 2011 10:49:28 +0200 |  | ||||||
| Subject: [PATCH 06/21] MTD: NAND: JZ4740: Multi-bank support with |  | ||||||
|  autodetection |  | ||||||
|  |  | ||||||
| The platform data can now specify which external memory banks to probe |  | ||||||
| for NAND chips, and in which order. Banks that contain a NAND are used |  | ||||||
| and the other banks are freed. |  | ||||||
|  |  | ||||||
| Squashed version of development done in jz-2.6.38 branch. |  | ||||||
| Original patch by Lars-Peter Clausen with some bug fixes from me. |  | ||||||
| Thanks to Paul Cercueil for the initial autodetection patch. |  | ||||||
| --- |  | ||||||
|  arch/mips/include/asm/mach-jz4740/jz4740_nand.h |    4 + |  | ||||||
|  arch/mips/jz4740/platform.c                     |   20 ++- |  | ||||||
|  drivers/mtd/nand/jz4740_nand.c                  |  228 +++++++++++++++++++---- |  | ||||||
|  3 files changed, 215 insertions(+), 37 deletions(-) |  | ||||||
|  |  | ||||||
| --- a/arch/mips/include/asm/mach-jz4740/jz4740_nand.h |  | ||||||
| +++ b/arch/mips/include/asm/mach-jz4740/jz4740_nand.h |  | ||||||
| @@ -19,6 +19,8 @@ |  | ||||||
|  #include <linux/mtd/nand.h> |  | ||||||
|  #include <linux/mtd/partitions.h> |  | ||||||
|   |  | ||||||
| +#define JZ_NAND_NUM_BANKS 4 |  | ||||||
| + |  | ||||||
|  struct jz_nand_platform_data { |  | ||||||
|  	int			num_partitions; |  | ||||||
|  	struct mtd_partition	*partitions; |  | ||||||
| @@ -27,6 +29,8 @@ struct jz_nand_platform_data { |  | ||||||
|   |  | ||||||
|  	unsigned int busy_gpio; |  | ||||||
|   |  | ||||||
| +	unsigned char banks[JZ_NAND_NUM_BANKS]; |  | ||||||
| + |  | ||||||
|  	void (*ident_callback)(struct platform_device *, struct nand_chip *, |  | ||||||
|  				struct mtd_partition **, int *num_partitions); |  | ||||||
|  }; |  | ||||||
| --- a/arch/mips/jz4740/platform.c |  | ||||||
| +++ b/arch/mips/jz4740/platform.c |  | ||||||
| @@ -157,11 +157,29 @@ static struct resource jz4740_nand_resou |  | ||||||
|  		.flags	= IORESOURCE_MEM, |  | ||||||
|  	}, |  | ||||||
|  	{ |  | ||||||
| -		.name	= "bank", |  | ||||||
| +		.name	= "bank1", |  | ||||||
|  		.start	= 0x18000000, |  | ||||||
|  		.end	= 0x180C0000 - 1, |  | ||||||
|  		.flags = IORESOURCE_MEM, |  | ||||||
|  	}, |  | ||||||
| +	{ |  | ||||||
| +		.name	= "bank2", |  | ||||||
| +		.start	= 0x14000000, |  | ||||||
| +		.end	= 0x140C0000 - 1, |  | ||||||
| +		.flags = IORESOURCE_MEM, |  | ||||||
| +	}, |  | ||||||
| +	{ |  | ||||||
| +		.name	= "bank3", |  | ||||||
| +		.start	= 0x0C000000, |  | ||||||
| +		.end	= 0x0C0C0000 - 1, |  | ||||||
| +		.flags = IORESOURCE_MEM, |  | ||||||
| +	}, |  | ||||||
| +	{ |  | ||||||
| +		.name	= "bank4", |  | ||||||
| +		.start	= 0x08000000, |  | ||||||
| +		.end	= 0x080C0000 - 1, |  | ||||||
| +		.flags = IORESOURCE_MEM, |  | ||||||
| +	}, |  | ||||||
|  }; |  | ||||||
|   |  | ||||||
|  struct platform_device jz4740_nand_device = { |  | ||||||
| --- a/drivers/mtd/nand/jz4740_nand.c |  | ||||||
| +++ b/drivers/mtd/nand/jz4740_nand.c |  | ||||||
| @@ -52,9 +52,10 @@ |  | ||||||
|   |  | ||||||
|  #define JZ_NAND_CTRL_ENABLE_CHIP(x) BIT((x) << 1) |  | ||||||
|  #define JZ_NAND_CTRL_ASSERT_CHIP(x) BIT(((x) << 1) + 1) |  | ||||||
| +#define JZ_NAND_CTRL_ASSERT_CHIP_MASK 0xaa |  | ||||||
|   |  | ||||||
| -#define JZ_NAND_MEM_ADDR_OFFSET 0x10000 |  | ||||||
|  #define JZ_NAND_MEM_CMD_OFFSET 0x08000 |  | ||||||
| +#define JZ_NAND_MEM_ADDR_OFFSET 0x10000 |  | ||||||
|   |  | ||||||
|  struct jz_nand { |  | ||||||
|  	struct mtd_info mtd; |  | ||||||
| @@ -62,8 +63,11 @@ struct jz_nand { |  | ||||||
|  	void __iomem *base; |  | ||||||
|  	struct resource *mem; |  | ||||||
|   |  | ||||||
| -	void __iomem *bank_base; |  | ||||||
| -	struct resource *bank_mem; |  | ||||||
| +	unsigned char banks[JZ_NAND_NUM_BANKS]; |  | ||||||
| +	void __iomem *bank_base[JZ_NAND_NUM_BANKS]; |  | ||||||
| +	struct resource *bank_mem[JZ_NAND_NUM_BANKS]; |  | ||||||
| + |  | ||||||
| +	int selected_bank; |  | ||||||
|   |  | ||||||
|  	struct jz_nand_platform_data *pdata; |  | ||||||
|  	bool is_reading; |  | ||||||
| @@ -74,26 +78,50 @@ static inline struct jz_nand *mtd_to_jz_ |  | ||||||
|  	return container_of(mtd, struct jz_nand, mtd); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| +static void jz_nand_select_chip(struct mtd_info *mtd, int chipnr) |  | ||||||
| +{ |  | ||||||
| +	struct jz_nand *nand = mtd_to_jz_nand(mtd); |  | ||||||
| +	struct nand_chip *chip = mtd->priv; |  | ||||||
| +	uint32_t ctrl; |  | ||||||
| +	int banknr; |  | ||||||
| + |  | ||||||
| +	ctrl = readl(nand->base + JZ_REG_NAND_CTRL); |  | ||||||
| +	ctrl &= ~JZ_NAND_CTRL_ASSERT_CHIP_MASK; |  | ||||||
| + |  | ||||||
| +	if (chipnr == -1) { |  | ||||||
| +		banknr = -1; |  | ||||||
| +	} else { |  | ||||||
| +		banknr = nand->banks[chipnr] - 1; |  | ||||||
| +		chip->IO_ADDR_R = nand->bank_base[banknr]; |  | ||||||
| +		chip->IO_ADDR_W = nand->bank_base[banknr]; |  | ||||||
| +	} |  | ||||||
| +	writel(ctrl, nand->base + JZ_REG_NAND_CTRL); |  | ||||||
| + |  | ||||||
| +	nand->selected_bank = banknr; |  | ||||||
| +} |  | ||||||
| + |  | ||||||
|  static void jz_nand_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl) |  | ||||||
|  { |  | ||||||
|  	struct jz_nand *nand = mtd_to_jz_nand(mtd); |  | ||||||
|  	struct nand_chip *chip = mtd->priv; |  | ||||||
|  	uint32_t reg; |  | ||||||
| +	void __iomem *bank_base = nand->bank_base[nand->selected_bank]; |  | ||||||
| + |  | ||||||
| +	BUG_ON(nand->selected_bank < 0); |  | ||||||
|   |  | ||||||
|  	if (ctrl & NAND_CTRL_CHANGE) { |  | ||||||
|  		BUG_ON((ctrl & NAND_ALE) && (ctrl & NAND_CLE)); |  | ||||||
|  		if (ctrl & NAND_ALE) |  | ||||||
| -			chip->IO_ADDR_W = nand->bank_base + JZ_NAND_MEM_ADDR_OFFSET; |  | ||||||
| +			bank_base += JZ_NAND_MEM_ADDR_OFFSET; |  | ||||||
|  		else if (ctrl & NAND_CLE) |  | ||||||
| -			chip->IO_ADDR_W = nand->bank_base + JZ_NAND_MEM_CMD_OFFSET; |  | ||||||
| -		else |  | ||||||
| -			chip->IO_ADDR_W = nand->bank_base; |  | ||||||
| +			bank_base += JZ_NAND_MEM_CMD_OFFSET; |  | ||||||
| +		chip->IO_ADDR_W = bank_base; |  | ||||||
|   |  | ||||||
|  		reg = readl(nand->base + JZ_REG_NAND_CTRL); |  | ||||||
|  		if (ctrl & NAND_NCE) |  | ||||||
| -			reg |= JZ_NAND_CTRL_ASSERT_CHIP(0); |  | ||||||
| +			reg |= JZ_NAND_CTRL_ASSERT_CHIP(nand->selected_bank); |  | ||||||
|  		else |  | ||||||
| -			reg &= ~JZ_NAND_CTRL_ASSERT_CHIP(0); |  | ||||||
| +			reg &= ~JZ_NAND_CTRL_ASSERT_CHIP(nand->selected_bank); |  | ||||||
|  		writel(reg, nand->base + JZ_REG_NAND_CTRL); |  | ||||||
|  	} |  | ||||||
|  	if (dat != NAND_CMD_NONE) |  | ||||||
| @@ -252,7 +280,7 @@ static int jz_nand_correct_ecc_rs(struct |  | ||||||
|  } |  | ||||||
|   |  | ||||||
|  static int jz_nand_ioremap_resource(struct platform_device *pdev, |  | ||||||
| -	const char *name, struct resource **res, void __iomem **base) |  | ||||||
| +	const char *name, struct resource **res, void *__iomem *base) |  | ||||||
|  { |  | ||||||
|  	int ret; |  | ||||||
|   |  | ||||||
| @@ -288,6 +316,90 @@ err: |  | ||||||
|  	return ret; |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| +static inline void jz_nand_iounmap_resource(struct resource *res, void __iomem *base) |  | ||||||
| +{ |  | ||||||
| +	iounmap(base); |  | ||||||
| +	release_mem_region(res->start, resource_size(res)); |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static int __devinit jz_nand_detect_bank(struct platform_device *pdev, struct jz_nand *nand, unsigned char bank, size_t chipnr, uint8_t *nand_maf_id, uint8_t *nand_dev_id) { |  | ||||||
| +	int ret; |  | ||||||
| +	int gpio; |  | ||||||
| +	char gpio_name[9]; |  | ||||||
| +	char res_name[6]; |  | ||||||
| +	uint32_t ctrl; |  | ||||||
| +	struct mtd_info *mtd = &nand->mtd; |  | ||||||
| +	struct nand_chip *chip = &nand->chip; |  | ||||||
| + |  | ||||||
| +	/* Request GPIO port. */ |  | ||||||
| +	gpio = JZ_GPIO_MEM_CS0 + bank - 1; |  | ||||||
| +	sprintf(gpio_name, "NAND CS%d", bank); |  | ||||||
| +	ret = gpio_request(gpio, gpio_name); |  | ||||||
| +	if (ret) { |  | ||||||
| +		dev_warn(&pdev->dev, |  | ||||||
| +			"Failed to request %s gpio %d: %d\n", |  | ||||||
| +			gpio_name, gpio, ret); |  | ||||||
| +		goto notfound_gpio; |  | ||||||
| +	} |  | ||||||
| + |  | ||||||
| +	/* Request I/O resource. */ |  | ||||||
| +	sprintf(res_name, "bank%d", bank); |  | ||||||
| +	ret = jz_nand_ioremap_resource(pdev, res_name, |  | ||||||
| +					&nand->bank_mem[bank - 1], |  | ||||||
| +					&nand->bank_base[bank - 1]); |  | ||||||
| +	if (ret) |  | ||||||
| +		goto notfound_resource; |  | ||||||
| + |  | ||||||
| +	/* Enable chip in bank. */ |  | ||||||
| +	jz_gpio_set_function(gpio, JZ_GPIO_FUNC_MEM_CS0); |  | ||||||
| +	ctrl = readl(nand->base + JZ_REG_NAND_CTRL); |  | ||||||
| +	ctrl |= JZ_NAND_CTRL_ENABLE_CHIP(bank - 1); |  | ||||||
| +	writel(ctrl, nand->base + JZ_REG_NAND_CTRL); |  | ||||||
| + |  | ||||||
| +	if (chipnr == 0) { |  | ||||||
| +		/* Detect first chip. */ |  | ||||||
| +		ret = nand_scan_ident(mtd, 1, NULL); |  | ||||||
| +		if (ret) |  | ||||||
| +			goto notfound_id; |  | ||||||
| + |  | ||||||
| +		/* Retrieve the IDs from the first chip. */ |  | ||||||
| +		chip->select_chip(mtd, 0); |  | ||||||
| +		chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); |  | ||||||
| +		chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); |  | ||||||
| +		*nand_maf_id = chip->read_byte(mtd); |  | ||||||
| +		*nand_dev_id = chip->read_byte(mtd); |  | ||||||
| +	} else { |  | ||||||
| +		/* Detect additional chip. */ |  | ||||||
| +		chip->select_chip(mtd, chipnr); |  | ||||||
| +		chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); |  | ||||||
| +		chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); |  | ||||||
| +		if (*nand_maf_id != chip->read_byte(mtd) |  | ||||||
| +		 || *nand_dev_id != chip->read_byte(mtd)) { |  | ||||||
| +			ret = -ENODEV; |  | ||||||
| +			goto notfound_id; |  | ||||||
| +		} |  | ||||||
| + |  | ||||||
| +		/* Update size of the MTD. */ |  | ||||||
| +		chip->numchips++; |  | ||||||
| +		mtd->size += chip->chipsize; |  | ||||||
| +	} |  | ||||||
| + |  | ||||||
| +	dev_info(&pdev->dev, "Found chip %i on bank %i\n", chipnr, bank); |  | ||||||
| +	return 0; |  | ||||||
| + |  | ||||||
| +notfound_id: |  | ||||||
| +	dev_info(&pdev->dev, "No chip found on bank %i\n", bank); |  | ||||||
| +	ctrl &= ~(JZ_NAND_CTRL_ENABLE_CHIP(bank - 1)); |  | ||||||
| +	writel(ctrl, nand->base + JZ_REG_NAND_CTRL); |  | ||||||
| +	jz_gpio_set_function(gpio, JZ_GPIO_FUNC_NONE); |  | ||||||
| +	jz_nand_iounmap_resource(nand->bank_mem[bank - 1], |  | ||||||
| +				 nand->bank_base[bank - 1]); |  | ||||||
| +notfound_resource: |  | ||||||
| +	gpio_free(gpio); |  | ||||||
| +notfound_gpio: |  | ||||||
| +	return ret; |  | ||||||
| +} |  | ||||||
| + |  | ||||||
|  static int __devinit jz_nand_probe(struct platform_device *pdev) |  | ||||||
|  { |  | ||||||
|  	int ret; |  | ||||||
| @@ -295,6 +407,8 @@ static int __devinit jz_nand_probe(struc |  | ||||||
|  	struct nand_chip *chip; |  | ||||||
|  	struct mtd_info *mtd; |  | ||||||
|  	struct jz_nand_platform_data *pdata = pdev->dev.platform_data; |  | ||||||
| +	size_t chipnr, bank_idx; |  | ||||||
| +	uint8_t nand_maf_id = 0, nand_dev_id = 0; |  | ||||||
|   |  | ||||||
|  	nand = kzalloc(sizeof(*nand), GFP_KERNEL); |  | ||||||
|  	if (!nand) { |  | ||||||
| @@ -305,10 +419,6 @@ static int __devinit jz_nand_probe(struc |  | ||||||
|  	ret = jz_nand_ioremap_resource(pdev, "mmio", &nand->mem, &nand->base); |  | ||||||
|  	if (ret) |  | ||||||
|  		goto err_free; |  | ||||||
| -	ret = jz_nand_ioremap_resource(pdev, "bank", &nand->bank_mem, |  | ||||||
| -			&nand->bank_base); |  | ||||||
| -	if (ret) |  | ||||||
| -		goto err_iounmap_mmio; |  | ||||||
|   |  | ||||||
|  	if (pdata && gpio_is_valid(pdata->busy_gpio)) { |  | ||||||
|  		ret = gpio_request(pdata->busy_gpio, "NAND busy pin"); |  | ||||||
| @@ -316,7 +426,7 @@ static int __devinit jz_nand_probe(struc |  | ||||||
|  			dev_err(&pdev->dev, |  | ||||||
|  				"Failed to request busy gpio %d: %d\n", |  | ||||||
|  				pdata->busy_gpio, ret); |  | ||||||
| -			goto err_iounmap_mem; |  | ||||||
| +			goto err_iounmap_mmio; |  | ||||||
|  		} |  | ||||||
|  	} |  | ||||||
|   |  | ||||||
| @@ -338,22 +448,51 @@ static int __devinit jz_nand_probe(struc |  | ||||||
|   |  | ||||||
|  	chip->chip_delay = 50; |  | ||||||
|  	chip->cmd_ctrl = jz_nand_cmd_ctrl; |  | ||||||
| +	chip->select_chip = jz_nand_select_chip; |  | ||||||
|   |  | ||||||
|  	if (pdata && gpio_is_valid(pdata->busy_gpio)) |  | ||||||
|  		chip->dev_ready = jz_nand_dev_ready; |  | ||||||
|   |  | ||||||
| -	chip->IO_ADDR_R = nand->bank_base; |  | ||||||
| -	chip->IO_ADDR_W = nand->bank_base; |  | ||||||
| - |  | ||||||
|  	nand->pdata = pdata; |  | ||||||
|  	platform_set_drvdata(pdev, nand); |  | ||||||
|   |  | ||||||
| -	writel(JZ_NAND_CTRL_ENABLE_CHIP(0), nand->base + JZ_REG_NAND_CTRL); |  | ||||||
| - |  | ||||||
| -	ret = nand_scan_ident(mtd, 1, NULL); |  | ||||||
| -	if (ret) { |  | ||||||
| -		dev_err(&pdev->dev,  "Failed to scan nand\n"); |  | ||||||
| -		goto err_gpio_free; |  | ||||||
| +	/* We are going to autodetect NAND chips in the banks specified in the |  | ||||||
| +	 * platform data. Although nand_scan_ident() can detect multiple chips, |  | ||||||
| +	 * it requires those chips to be numbered consecuitively, which is not |  | ||||||
| +	 * always the case for external memory banks. And a fixed chip-to-bank |  | ||||||
| +	 * mapping is not practical either, since for example Dingoo units |  | ||||||
| +	 * produced at different times have NAND chips in different banks. |  | ||||||
| +	 */ |  | ||||||
| +	chipnr = 0; |  | ||||||
| +	for (bank_idx = 0; bank_idx < JZ_NAND_NUM_BANKS; bank_idx++) { |  | ||||||
| +		unsigned char bank; |  | ||||||
| + |  | ||||||
| +		/* If there is no platform data, look for NAND in bank 1, |  | ||||||
| +		 * which is the most likely bank since it is the only one |  | ||||||
| +		 * that can be booted from. |  | ||||||
| +		 */ |  | ||||||
| +		bank = pdata ? pdata->banks[bank_idx] : bank_idx ^ 1; |  | ||||||
| +		if (bank == 0) |  | ||||||
| +			break; |  | ||||||
| +		if (bank > JZ_NAND_NUM_BANKS) { |  | ||||||
| +			dev_warn(&pdev->dev, |  | ||||||
| +				"Skipping non-existing bank: %d\n", bank); |  | ||||||
| +			continue; |  | ||||||
| +		} |  | ||||||
| +		/* The detection routine will directly or indirectly call |  | ||||||
| +		 * jz_nand_select_chip(), so nand->banks has to contain the |  | ||||||
| +		 * bank we're checking. |  | ||||||
| +		 */ |  | ||||||
| +		nand->banks[chipnr] = bank; |  | ||||||
| +		if (jz_nand_detect_bank(pdev, nand, bank, chipnr, |  | ||||||
| +					&nand_maf_id, &nand_dev_id) == 0) |  | ||||||
| +			chipnr++; |  | ||||||
| +		else |  | ||||||
| +			nand->banks[chipnr] = 0; |  | ||||||
| +	} |  | ||||||
| +	if (chipnr == 0) { |  | ||||||
| +		dev_err(&pdev->dev, "No NAND chips found\n"); |  | ||||||
| +		goto err_gpio_busy; |  | ||||||
|  	} |  | ||||||
|   |  | ||||||
|  	if (pdata && pdata->ident_callback) { |  | ||||||
| @@ -363,8 +502,8 @@ static int __devinit jz_nand_probe(struc |  | ||||||
|   |  | ||||||
|  	ret = nand_scan_tail(mtd); |  | ||||||
|  	if (ret) { |  | ||||||
| -		dev_err(&pdev->dev,  "Failed to scan nand\n"); |  | ||||||
| -		goto err_gpio_free; |  | ||||||
| +		dev_err(&pdev->dev,  "Failed to scan NAND\n"); |  | ||||||
| +		goto err_unclaim_banks; |  | ||||||
|  	} |  | ||||||
|   |  | ||||||
|  	ret = mtd_device_parse_register(mtd, NULL, 0, |  | ||||||
| @@ -381,14 +520,21 @@ static int __devinit jz_nand_probe(struc |  | ||||||
|  	return 0; |  | ||||||
|   |  | ||||||
|  err_nand_release: |  | ||||||
| -	nand_release(&nand->mtd); |  | ||||||
| -err_gpio_free: |  | ||||||
| +	nand_release(mtd); |  | ||||||
| +err_unclaim_banks: |  | ||||||
| +	while (chipnr--) { |  | ||||||
| +		unsigned char bank = nand->banks[chipnr]; |  | ||||||
| +		gpio_free(JZ_GPIO_MEM_CS0 + bank - 1); |  | ||||||
| +		jz_nand_iounmap_resource(nand->bank_mem[bank - 1], |  | ||||||
| +					 nand->bank_base[bank - 1]); |  | ||||||
| +	} |  | ||||||
| +	writel(0, nand->base + JZ_REG_NAND_CTRL); |  | ||||||
| +err_gpio_busy: |  | ||||||
| +	if (pdata && gpio_is_valid(pdata->busy_gpio)) |  | ||||||
| +		gpio_free(pdata->busy_gpio); |  | ||||||
|  	platform_set_drvdata(pdev, NULL); |  | ||||||
| -	gpio_free(pdata->busy_gpio); |  | ||||||
| -err_iounmap_mem: |  | ||||||
| -	iounmap(nand->bank_base); |  | ||||||
|  err_iounmap_mmio: |  | ||||||
| -	iounmap(nand->base); |  | ||||||
| +	jz_nand_iounmap_resource(nand->mem, nand->base); |  | ||||||
|  err_free: |  | ||||||
|  	kfree(nand); |  | ||||||
|  	return ret; |  | ||||||
| @@ -397,16 +543,26 @@ err_free: |  | ||||||
|  static int __devexit jz_nand_remove(struct platform_device *pdev) |  | ||||||
|  { |  | ||||||
|  	struct jz_nand *nand = platform_get_drvdata(pdev); |  | ||||||
| +	struct jz_nand_platform_data *pdata = pdev->dev.platform_data; |  | ||||||
| +	size_t i; |  | ||||||
|   |  | ||||||
|  	nand_release(&nand->mtd); |  | ||||||
|   |  | ||||||
|  	/* Deassert and disable all chips */ |  | ||||||
|  	writel(0, nand->base + JZ_REG_NAND_CTRL); |  | ||||||
|   |  | ||||||
| -	iounmap(nand->bank_base); |  | ||||||
| -	release_mem_region(nand->bank_mem->start, resource_size(nand->bank_mem)); |  | ||||||
| -	iounmap(nand->base); |  | ||||||
| -	release_mem_region(nand->mem->start, resource_size(nand->mem)); |  | ||||||
| +	for (i = 0; i < JZ_NAND_NUM_BANKS; ++i) { |  | ||||||
| +		unsigned char bank = nand->banks[i]; |  | ||||||
| +		if (bank != 0) { |  | ||||||
| +			jz_nand_iounmap_resource(nand->bank_mem[bank - 1], |  | ||||||
| +						 nand->bank_base[bank - 1]); |  | ||||||
| +			gpio_free(JZ_GPIO_MEM_CS0 + bank - 1); |  | ||||||
| +		} |  | ||||||
| +	} |  | ||||||
| +	if (pdata && gpio_is_valid(pdata->busy_gpio)) |  | ||||||
| +		gpio_free(pdata->busy_gpio); |  | ||||||
| + |  | ||||||
| +	jz_nand_iounmap_resource(nand->mem, nand->base); |  | ||||||
|   |  | ||||||
|  	platform_set_drvdata(pdev, NULL); |  | ||||||
|  	kfree(nand); |  | ||||||
| @@ -1,304 +0,0 @@ | |||||||
| From 2248fb9c47fe7e72c735d6c16aba27bf92e1673a Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Lars-Peter Clausen <lars@metafoo.de> |  | ||||||
| Date: Sun, 1 Aug 2010 21:19:40 +0200 |  | ||||||
| Subject: [PATCH 07/21] Add ili8960 lcd driver |  | ||||||
|  |  | ||||||
| --- |  | ||||||
|  drivers/video/backlight/Kconfig   |    7 + |  | ||||||
|  drivers/video/backlight/Makefile  |    1 + |  | ||||||
|  drivers/video/backlight/ili8960.c |  263 +++++++++++++++++++++++++++++++++++++ |  | ||||||
|  3 files changed, 271 insertions(+), 0 deletions(-) |  | ||||||
|  create mode 100644 drivers/video/backlight/ili8960.c |  | ||||||
|  |  | ||||||
| --- a/drivers/video/backlight/Kconfig |  | ||||||
| +++ b/drivers/video/backlight/Kconfig |  | ||||||
| @@ -59,6 +59,13 @@ config LCD_LTV350QV |  | ||||||
|   |  | ||||||
|  	  The LTV350QV panel is present on all ATSTK1000 boards. |  | ||||||
|   |  | ||||||
| +config LCD_ILI8960 |  | ||||||
| +	tristate "Ilitek ili8960 LCD driver" |  | ||||||
| +	depends on LCD_CLASS_DEVICE && SPI |  | ||||||
| +	default n |  | ||||||
| +	help |  | ||||||
| +	  Driver for the Ilitek ili8960 LCD controller chip. |  | ||||||
| + |  | ||||||
|  config LCD_ILI9320 |  | ||||||
|  	tristate |  | ||||||
|  	help |  | ||||||
| --- a/drivers/video/backlight/Makefile |  | ||||||
| +++ b/drivers/video/backlight/Makefile |  | ||||||
| @@ -6,6 +6,7 @@ obj-$(CONFIG_LCD_HP700)		   += jornada72 |  | ||||||
|  obj-$(CONFIG_LCD_L4F00242T03)	   += l4f00242t03.o |  | ||||||
|  obj-$(CONFIG_LCD_LMS283GF05)	   += lms283gf05.o |  | ||||||
|  obj-$(CONFIG_LCD_LTV350QV)	   += ltv350qv.o |  | ||||||
| +obj-$(CONFIG_LCD_ILI8960)	   += ili8960.o |  | ||||||
|  obj-$(CONFIG_LCD_ILI9320)	   += ili9320.o |  | ||||||
|  obj-$(CONFIG_LCD_PLATFORM)	   += platform_lcd.o |  | ||||||
|  obj-$(CONFIG_LCD_VGG2432A4)	   += vgg2432a4.o |  | ||||||
| --- /dev/null |  | ||||||
| +++ b/drivers/video/backlight/ili8960.c |  | ||||||
| @@ -0,0 +1,263 @@ |  | ||||||
| +/* |  | ||||||
| + *  Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de> |  | ||||||
| + *  Driver for Ilitek ili8960 LCD |  | ||||||
| + * |  | ||||||
| + *  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. |  | ||||||
| + * |  | ||||||
| + *  You should have received a copy of the  GNU General Public License along |  | ||||||
| + *  with this program; if not, write  to the Free Software Foundation, Inc., |  | ||||||
| + *  675 Mass Ave, Cambridge, MA 02139, USA. |  | ||||||
| + * |  | ||||||
| + */ |  | ||||||
| + |  | ||||||
| +#include <linux/module.h> |  | ||||||
| +#include <linux/spi/spi.h> |  | ||||||
| +#include <linux/lcd.h> |  | ||||||
| +#include <linux/backlight.h> |  | ||||||
| +#include <linux/delay.h> |  | ||||||
| + |  | ||||||
| +struct ili8960 { |  | ||||||
| +	struct spi_device *spi; |  | ||||||
| +	struct lcd_device *lcd; |  | ||||||
| +	struct backlight_device *bl; |  | ||||||
| +	bool enabled; |  | ||||||
| +	unsigned int brightness; |  | ||||||
| +}; |  | ||||||
| + |  | ||||||
| +#define ILI8960_REG_BRIGHTNESS	0x03 |  | ||||||
| +#define ILI8960_REG_POWER	0x05 |  | ||||||
| +#define ILI8960_REG_CONTRAST	0x0d |  | ||||||
| + |  | ||||||
| +static int ili8960_write_reg(struct spi_device *spi, uint8_t reg, |  | ||||||
| +				uint8_t data) |  | ||||||
| +{ |  | ||||||
| +	uint8_t buf[2]; |  | ||||||
| +	buf[0] = ((reg & 0x40) << 1) | (reg & 0x3f); |  | ||||||
| +	buf[1] = data; |  | ||||||
| + |  | ||||||
| +	return spi_write(spi, buf, sizeof(buf)); |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static int ili8960_programm_power(struct spi_device *spi, bool enabled) |  | ||||||
| +{ |  | ||||||
| +	int ret; |  | ||||||
| + |  | ||||||
| +	if (enabled) |  | ||||||
| +		mdelay(20); |  | ||||||
| + |  | ||||||
| +	ret = ili8960_write_reg(spi, ILI8960_REG_POWER, enabled ? 0xc7 : 0xc6); |  | ||||||
| + |  | ||||||
| +	if (!enabled) |  | ||||||
| +		mdelay(20); |  | ||||||
| + |  | ||||||
| +	return ret; |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static int ili8960_set_power(struct lcd_device *lcd, int power) |  | ||||||
| +{ |  | ||||||
| +	struct ili8960 *ili8960 = lcd_get_data(lcd); |  | ||||||
| + |  | ||||||
| +	switch (power) { |  | ||||||
| +	case FB_BLANK_UNBLANK: |  | ||||||
| +		ili8960->enabled = true; |  | ||||||
| +		break; |  | ||||||
| +	default: |  | ||||||
| +		ili8960->enabled = false; |  | ||||||
| +		break; |  | ||||||
| +	} |  | ||||||
| + |  | ||||||
| +	return ili8960_programm_power(ili8960->spi, ili8960->enabled); |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static int ili8960_get_power(struct lcd_device *lcd) |  | ||||||
| +{ |  | ||||||
| +	struct ili8960 *ili8960 = lcd_get_data(lcd); |  | ||||||
| +	return ili8960->enabled ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN; |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static int ili8960_set_contrast(struct lcd_device *lcd, int contrast) |  | ||||||
| +{ |  | ||||||
| +	struct ili8960 *ili8960 = lcd_get_data(lcd); |  | ||||||
| + |  | ||||||
| +	return ili8960_write_reg(ili8960->spi, ILI8960_REG_CONTRAST, contrast); |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static int ili8960_set_mode(struct lcd_device *lcd, struct fb_videomode *mode) |  | ||||||
| +{ |  | ||||||
| +	if (mode->xres != 320 && mode->yres != 240) |  | ||||||
| +		return -EINVAL; |  | ||||||
| + |  | ||||||
| +	return 0; |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static int ili8960_set_brightness(struct ili8960 *ili8960, int brightness) |  | ||||||
| +{ |  | ||||||
| +	int ret; |  | ||||||
| + |  | ||||||
| +	ret = ili8960_write_reg(ili8960->spi, ILI8960_REG_BRIGHTNESS, brightness); |  | ||||||
| + |  | ||||||
| +	if (ret == 0) |  | ||||||
| +		ili8960->brightness = brightness; |  | ||||||
| + |  | ||||||
| +	return ret; |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static ssize_t ili8960_show_brightness(struct device *dev, |  | ||||||
| +		struct device_attribute *attr, char *buf) |  | ||||||
| +{ |  | ||||||
| +	struct lcd_device *ld = to_lcd_device(dev); |  | ||||||
| +	struct ili8960 *ili8960 = lcd_get_data(ld); |  | ||||||
| + |  | ||||||
| +	return sprintf(buf, "%u\n", ili8960->brightness); |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static ssize_t ili8960_store_brightness(struct device *dev, |  | ||||||
| +		struct device_attribute *attr, const char *buf, size_t count) |  | ||||||
| +{ |  | ||||||
| +	struct lcd_device *ld = to_lcd_device(dev); |  | ||||||
| +	struct ili8960 *ili8960 = lcd_get_data(ld); |  | ||||||
| +	unsigned long brightness; |  | ||||||
| +	int ret; |  | ||||||
| + |  | ||||||
| +	ret = strict_strtoul(buf, 0, &brightness); |  | ||||||
| +	if (ret) |  | ||||||
| +		return ret; |  | ||||||
| + |  | ||||||
| +	if (brightness > 255) |  | ||||||
| +		return -EINVAL; |  | ||||||
| + |  | ||||||
| +	ili8960_set_brightness(ili8960, brightness); |  | ||||||
| + |  | ||||||
| +	return count; |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| + |  | ||||||
| +static DEVICE_ATTR(brightness, 0644, ili8960_show_brightness, |  | ||||||
| +	ili8960_store_brightness); |  | ||||||
| + |  | ||||||
| +static struct lcd_ops ili8960_lcd_ops = { |  | ||||||
| +	.set_power = ili8960_set_power, |  | ||||||
| +	.get_power = ili8960_get_power, |  | ||||||
| +	.set_contrast = ili8960_set_contrast, |  | ||||||
| +	.set_mode = ili8960_set_mode, |  | ||||||
| +}; |  | ||||||
| + |  | ||||||
| +static int __devinit ili8960_probe(struct spi_device *spi) |  | ||||||
| +{ |  | ||||||
| +	int ret; |  | ||||||
| +	struct ili8960 *ili8960; |  | ||||||
| + |  | ||||||
| +	ili8960 = kmalloc(sizeof(*ili8960), GFP_KERNEL); |  | ||||||
| +	if (!ili8960) |  | ||||||
| +		return -ENOMEM; |  | ||||||
| + |  | ||||||
| +	spi->bits_per_word = 8; |  | ||||||
| +	spi->mode = SPI_MODE_3; |  | ||||||
| + |  | ||||||
| +	ret = spi_setup(spi); |  | ||||||
| +	if (ret) { |  | ||||||
| +		dev_err(&spi->dev, "Failed to setup spi\n"); |  | ||||||
| +		goto err_free_ili8960; |  | ||||||
| +	} |  | ||||||
| + |  | ||||||
| +	ili8960->spi = spi; |  | ||||||
| + |  | ||||||
| +	ili8960->lcd = lcd_device_register("ili8960-lcd", &spi->dev, ili8960, |  | ||||||
| +						&ili8960_lcd_ops); |  | ||||||
| + |  | ||||||
| +	if (IS_ERR(ili8960->lcd)) { |  | ||||||
| +		ret = PTR_ERR(ili8960->lcd); |  | ||||||
| +		dev_err(&spi->dev, "Failed to register lcd device: %d\n", ret); |  | ||||||
| +		goto err_free_ili8960; |  | ||||||
| +	} |  | ||||||
| + |  | ||||||
| +	ili8960->lcd->props.max_contrast = 255; |  | ||||||
| + |  | ||||||
| +	ret = device_create_file(&ili8960->lcd->dev, &dev_attr_brightness); |  | ||||||
| +	if (ret) |  | ||||||
| +		goto err_unregister_lcd; |  | ||||||
| + |  | ||||||
| +	ili8960_programm_power(ili8960->spi, true); |  | ||||||
| +	ili8960->enabled = true; |  | ||||||
| + |  | ||||||
| +	spi_set_drvdata(spi, ili8960); |  | ||||||
| + |  | ||||||
| +	ili8960_write_reg(spi, 0x13, 0x01); |  | ||||||
| + |  | ||||||
| +	return 0; |  | ||||||
| +err_unregister_lcd: |  | ||||||
| +	lcd_device_unregister(ili8960->lcd); |  | ||||||
| +err_free_ili8960: |  | ||||||
| +	kfree(ili8960); |  | ||||||
| +	return ret; |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static int __devexit ili8960_remove(struct spi_device *spi) |  | ||||||
| +{ |  | ||||||
| +	struct ili8960 *ili8960 = spi_get_drvdata(spi); |  | ||||||
| + |  | ||||||
| +	device_remove_file(&ili8960->lcd->dev, &dev_attr_brightness); |  | ||||||
| +	lcd_device_unregister(ili8960->lcd); |  | ||||||
| + |  | ||||||
| +	spi_set_drvdata(spi, NULL); |  | ||||||
| +	kfree(ili8960); |  | ||||||
| +	return 0; |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +#ifdef CONFIG_PM |  | ||||||
| + |  | ||||||
| +static int ili8960_suspend(struct spi_device *spi, pm_message_t state) |  | ||||||
| +{ |  | ||||||
| +	struct ili8960 *ili8960 = spi_get_drvdata(spi); |  | ||||||
| + |  | ||||||
| +	if (ili8960->enabled) |  | ||||||
| +		ili8960_programm_power(ili8960->spi, false); |  | ||||||
| + |  | ||||||
| +	return 0; |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static int ili8960_resume(struct spi_device *spi) |  | ||||||
| +{ |  | ||||||
| +	struct ili8960 *ili8960 = spi_get_drvdata(spi); |  | ||||||
| + |  | ||||||
| +	if (ili8960->enabled) |  | ||||||
| +		ili8960_programm_power(ili8960->spi, true); |  | ||||||
| + |  | ||||||
| +	return 0; |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +#else |  | ||||||
| +#define ili8960_suspend NULL |  | ||||||
| +#define ili8960_resume NULL |  | ||||||
| +#endif |  | ||||||
| + |  | ||||||
| +static struct spi_driver ili8960_driver = { |  | ||||||
| +	.driver = { |  | ||||||
| +		.name = "ili8960", |  | ||||||
| +		.owner = THIS_MODULE, |  | ||||||
| +	}, |  | ||||||
| +	.probe = ili8960_probe, |  | ||||||
| +	.remove = __devexit_p(ili8960_remove), |  | ||||||
| +	.suspend = ili8960_suspend, |  | ||||||
| +	.resume = ili8960_resume, |  | ||||||
| +}; |  | ||||||
| + |  | ||||||
| +static int __init ili8960_init(void) |  | ||||||
| +{ |  | ||||||
| +	return spi_register_driver(&ili8960_driver); |  | ||||||
| +} |  | ||||||
| +module_init(ili8960_init); |  | ||||||
| + |  | ||||||
| +static void __exit ili8960_exit(void) |  | ||||||
| +{ |  | ||||||
| +	spi_unregister_driver(&ili8960_driver); |  | ||||||
| +} |  | ||||||
| +module_exit(ili8960_exit) |  | ||||||
| + |  | ||||||
| +MODULE_AUTHOR("Lars-Peter Clausen"); |  | ||||||
| +MODULE_LICENSE("GPL"); |  | ||||||
| +MODULE_DESCRIPTION("LCD driver for Ilitek ili8960"); |  | ||||||
| +MODULE_ALIAS("spi:ili8960"); |  | ||||||
| @@ -1,21 +0,0 @@ | |||||||
| From e5f25e25ed6c0478cbba7a32891b911e3183dad4 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Lars-Peter Clausen <lars@metafoo.de> |  | ||||||
| Date: Wed, 13 Oct 2010 01:17:24 +0200 |  | ||||||
| Subject: [PATCH 08/21] qi_lb60: Don't use 3-wire spi mode for the display for |  | ||||||
|  now |  | ||||||
|  |  | ||||||
| The spi_gpio driver does not support 3-wire mode. |  | ||||||
| --- |  | ||||||
|  arch/mips/jz4740/board-qi_lb60.c |    1 - |  | ||||||
|  1 files changed, 0 insertions(+), 1 deletions(-) |  | ||||||
|  |  | ||||||
| --- a/arch/mips/jz4740/board-qi_lb60.c |  | ||||||
| +++ b/arch/mips/jz4740/board-qi_lb60.c |  | ||||||
| @@ -310,7 +310,6 @@ static struct spi_board_info qi_lb60_spi |  | ||||||
|  		.chip_select = 0, |  | ||||||
|  		.bus_num = 1, |  | ||||||
|  		.max_speed_hz = 30 * 1000, |  | ||||||
| -		.mode = SPI_3WIRE, |  | ||||||
|  	}, |  | ||||||
|  }; |  | ||||||
|   |  | ||||||
| @@ -1,124 +0,0 @@ | |||||||
| From 4003b9a2c05f4d0d37535c3dffbf4a7b47d5c36c Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Maarten ter Huurne <maarten@treewalker.org> |  | ||||||
| Date: Wed, 8 Sep 2010 02:31:19 +0200 |  | ||||||
| Subject: [PATCH 09/21] /dev/mem: Add kernel config option to omit this |  | ||||||
|  device. |  | ||||||
|  |  | ||||||
| Omitting this device prevents software from accessing the hardware directly, which can cause trouble if the kernel accesses the same hardware. |  | ||||||
| It also saves some space on embedded systems. |  | ||||||
| --- |  | ||||||
|  arch/x86/Kconfig.debug |    1 + |  | ||||||
|  drivers/char/Kconfig   |   10 ++++++++++ |  | ||||||
|  drivers/char/mem.c     |   17 +++++++++++++++++ |  | ||||||
|  3 files changed, 28 insertions(+), 0 deletions(-) |  | ||||||
|  |  | ||||||
| --- a/arch/x86/Kconfig.debug |  | ||||||
| +++ b/arch/x86/Kconfig.debug |  | ||||||
| @@ -7,6 +7,7 @@ source "lib/Kconfig.debug" |  | ||||||
|   |  | ||||||
|  config STRICT_DEVMEM |  | ||||||
|  	bool "Filter access to /dev/mem" |  | ||||||
| +	depends on DEVMEM |  | ||||||
|  	---help--- |  | ||||||
|  	  If this option is disabled, you allow userspace (root) access to all |  | ||||||
|  	  of memory, including kernel and userspace memory. Accidental |  | ||||||
| --- a/drivers/char/Kconfig |  | ||||||
| +++ b/drivers/char/Kconfig |  | ||||||
| @@ -6,6 +6,16 @@ menu "Character devices" |  | ||||||
|   |  | ||||||
|  source "drivers/tty/Kconfig" |  | ||||||
|   |  | ||||||
| +config DEVMEM |  | ||||||
| +	bool "/dev/mem virtual device support" |  | ||||||
| +	default y |  | ||||||
| +	help |  | ||||||
| +	  Say Y here if you want to support the /dev/mem device. |  | ||||||
| +	  Some X server drivers access the video hardware using this device. |  | ||||||
| +	  Accessing hardware directly from user space can be useful in some |  | ||||||
| +	  cases, but it is not without risks. |  | ||||||
| +	  When in doubt, say "N". |  | ||||||
| + |  | ||||||
|  config DEVKMEM |  | ||||||
|  	bool "/dev/kmem virtual device support" |  | ||||||
|  	default y |  | ||||||
| --- a/drivers/char/mem.c |  | ||||||
| +++ b/drivers/char/mem.c |  | ||||||
| @@ -87,6 +87,8 @@ void __weak unxlate_dev_mem_ptr(unsigned |  | ||||||
|  { |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| +#ifdef CONFIG_DEVMEM |  | ||||||
| + |  | ||||||
|  /* |  | ||||||
|   * This funcion reads the *physical* memory. The f_pos points directly to the |  | ||||||
|   * memory location. |  | ||||||
| @@ -210,6 +212,10 @@ static ssize_t write_mem(struct file *fi |  | ||||||
|  	return written; |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| +#endif |  | ||||||
| + |  | ||||||
| +#if defined(CONFIG_DEVMEM) || defined(CONFIG_DEVKMEM) |  | ||||||
| + |  | ||||||
|  int __weak phys_mem_access_prot_allowed(struct file *file, |  | ||||||
|  	unsigned long pfn, unsigned long size, pgprot_t *vma_prot) |  | ||||||
|  { |  | ||||||
| @@ -331,6 +337,8 @@ static int mmap_mem(struct file *file, s |  | ||||||
|  	return 0; |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| +#endif |  | ||||||
| + |  | ||||||
|  #ifdef CONFIG_DEVKMEM |  | ||||||
|  static int mmap_kmem(struct file *file, struct vm_area_struct *vma) |  | ||||||
|  { |  | ||||||
| @@ -694,6 +702,7 @@ static loff_t null_lseek(struct file *fi |  | ||||||
|  	return file->f_pos = 0; |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| +#if defined(CONFIG_DEVMEM) || defined(CONFIG_DEVKMEM) || defined(CONFIG_DEVPORT) |  | ||||||
|  /* |  | ||||||
|   * The memory devices use the full 32/64 bits of the offset, and so we cannot |  | ||||||
|   * check against negative addresses: they are ok. The return value is weird, |  | ||||||
| @@ -726,11 +735,15 @@ static loff_t memory_lseek(struct file * |  | ||||||
|  	mutex_unlock(&file->f_path.dentry->d_inode->i_mutex); |  | ||||||
|  	return ret; |  | ||||||
|  } |  | ||||||
| +#endif |  | ||||||
|   |  | ||||||
| +#if defined(CONFIG_DEVMEM) || defined(CONFIG_DEVKMEM) || \ |  | ||||||
| +		defined(CONFIG_DEVPORT) || defined(CONFIG_CRASH_DUMP) |  | ||||||
|  static int open_port(struct inode * inode, struct file * filp) |  | ||||||
|  { |  | ||||||
|  	return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; |  | ||||||
|  } |  | ||||||
| +#endif |  | ||||||
|   |  | ||||||
|  #define zero_lseek	null_lseek |  | ||||||
|  #define full_lseek      null_lseek |  | ||||||
| @@ -740,6 +753,7 @@ static int open_port(struct inode * inod |  | ||||||
|  #define open_kmem	open_mem |  | ||||||
|  #define open_oldmem	open_mem |  | ||||||
|   |  | ||||||
| +#ifdef CONFIG_DEVMEM |  | ||||||
|  static const struct file_operations mem_fops = { |  | ||||||
|  	.llseek		= memory_lseek, |  | ||||||
|  	.read		= read_mem, |  | ||||||
| @@ -748,6 +762,7 @@ static const struct file_operations mem_ |  | ||||||
|  	.open		= open_mem, |  | ||||||
|  	.get_unmapped_area = get_unmapped_area_mem, |  | ||||||
|  }; |  | ||||||
| +#endif |  | ||||||
|   |  | ||||||
|  #ifdef CONFIG_DEVKMEM |  | ||||||
|  static const struct file_operations kmem_fops = { |  | ||||||
| @@ -851,7 +866,9 @@ static const struct memdev { |  | ||||||
|  	const struct file_operations *fops; |  | ||||||
|  	struct backing_dev_info *dev_info; |  | ||||||
|  } devlist[] = { |  | ||||||
| +#ifdef CONFIG_DEVMEM |  | ||||||
|  	 [1] = { "mem", 0, &mem_fops, &directly_mappable_cdev_bdi }, |  | ||||||
| +#endif |  | ||||||
|  #ifdef CONFIG_DEVKMEM |  | ||||||
|  	 [2] = { "kmem", 0, &kmem_fops, &directly_mappable_cdev_bdi }, |  | ||||||
|  #endif |  | ||||||
| @@ -1,301 +0,0 @@ | |||||||
| From ca40c7542f0cd0e0dfa074bd4ccefc04b8561427 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Maarten ter Huurne <maarten@treewalker.org> |  | ||||||
| Date: Tue, 2 Aug 2011 10:26:09 +0200 |  | ||||||
| Subject: [PATCH 10/21] cpufreq_stats: Support runtime changes to frequency |  | ||||||
|  table. |  | ||||||
|  |  | ||||||
| --- |  | ||||||
|  drivers/cpufreq/cpufreq_stats.c |  161 ++++++++++++++++++++------------------- |  | ||||||
|  1 files changed, 83 insertions(+), 78 deletions(-) |  | ||||||
|  |  | ||||||
| --- a/drivers/cpufreq/cpufreq_stats.c |  | ||||||
| +++ b/drivers/cpufreq/cpufreq_stats.c |  | ||||||
| @@ -20,6 +20,7 @@ |  | ||||||
|  #include <linux/kobject.h> |  | ||||||
|  #include <linux/spinlock.h> |  | ||||||
|  #include <linux/notifier.h> |  | ||||||
| +#include <linux/string.h> |  | ||||||
|  #include <asm/cputime.h> |  | ||||||
|   |  | ||||||
|  static spinlock_t cpufreq_stats_lock; |  | ||||||
| @@ -36,7 +37,7 @@ struct cpufreq_stats { |  | ||||||
|  	unsigned long long  last_time; |  | ||||||
|  	unsigned int max_state; |  | ||||||
|  	unsigned int state_num; |  | ||||||
| -	unsigned int last_index; |  | ||||||
| +	int last_index; |  | ||||||
|  	cputime64_t *time_in_state; |  | ||||||
|  	unsigned int *freq_table; |  | ||||||
|  #ifdef CONFIG_CPU_FREQ_STAT_DETAILS |  | ||||||
| @@ -59,7 +60,7 @@ static int cpufreq_stats_update(unsigned |  | ||||||
|  	cur_time = get_jiffies_64(); |  | ||||||
|  	spin_lock(&cpufreq_stats_lock); |  | ||||||
|  	stat = per_cpu(cpufreq_stats_table, cpu); |  | ||||||
| -	if (stat->time_in_state) |  | ||||||
| +	if (stat->time_in_state && stat->last_index != -1) |  | ||||||
|  		stat->time_in_state[stat->last_index] += |  | ||||||
|  			cur_time - stat->last_time; |  | ||||||
|  	stat->last_time = cur_time; |  | ||||||
| @@ -81,7 +82,7 @@ static ssize_t show_time_in_state(struct |  | ||||||
|  	ssize_t len = 0; |  | ||||||
|  	int i; |  | ||||||
|  	struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, policy->cpu); |  | ||||||
| -	if (!stat) |  | ||||||
| +	if (!stat || !stat->time_in_state) |  | ||||||
|  		return 0; |  | ||||||
|  	cpufreq_stats_update(stat->cpu); |  | ||||||
|  	for (i = 0; i < stat->state_num; i++) { |  | ||||||
| @@ -99,7 +100,7 @@ static ssize_t show_trans_table(struct c |  | ||||||
|  	int i, j; |  | ||||||
|   |  | ||||||
|  	struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, policy->cpu); |  | ||||||
| -	if (!stat) |  | ||||||
| +	if (!stat || !stat->trans_table) |  | ||||||
|  		return 0; |  | ||||||
|  	cpufreq_stats_update(stat->cpu); |  | ||||||
|  	len += snprintf(buf + len, PAGE_SIZE - len, "   From  :    To\n"); |  | ||||||
| @@ -158,63 +159,35 @@ static struct attribute_group stats_attr |  | ||||||
|  static int freq_table_get_index(struct cpufreq_stats *stat, unsigned int freq) |  | ||||||
|  { |  | ||||||
|  	int index; |  | ||||||
| -	for (index = 0; index < stat->max_state; index++) |  | ||||||
| -		if (stat->freq_table[index] == freq) |  | ||||||
| -			return index; |  | ||||||
| +	if (stat->freq_table) |  | ||||||
| +		for (index = 0; index < stat->max_state; index++) |  | ||||||
| +			if (stat->freq_table[index] == freq) |  | ||||||
| +				return index; |  | ||||||
|  	return -1; |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| -/* should be called late in the CPU removal sequence so that the stats |  | ||||||
| - * memory is still available in case someone tries to use it. |  | ||||||
| - */ |  | ||||||
|  static void cpufreq_stats_free_table(unsigned int cpu) |  | ||||||
|  { |  | ||||||
|  	struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, cpu); |  | ||||||
| +	struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); |  | ||||||
| +	if (policy && policy->cpu == cpu) |  | ||||||
| +		sysfs_remove_group(&policy->kobj, &stats_attr_group); |  | ||||||
|  	if (stat) { |  | ||||||
|  		kfree(stat->time_in_state); |  | ||||||
|  		kfree(stat); |  | ||||||
|  	} |  | ||||||
|  	per_cpu(cpufreq_stats_table, cpu) = NULL; |  | ||||||
| -} |  | ||||||
| - |  | ||||||
| -/* must be called early in the CPU removal sequence (before |  | ||||||
| - * cpufreq_remove_dev) so that policy is still valid. |  | ||||||
| - */ |  | ||||||
| -static void cpufreq_stats_free_sysfs(unsigned int cpu) |  | ||||||
| -{ |  | ||||||
| -	struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); |  | ||||||
| -	if (policy && policy->cpu == cpu) |  | ||||||
| -		sysfs_remove_group(&policy->kobj, &stats_attr_group); |  | ||||||
|  	if (policy) |  | ||||||
|  		cpufreq_cpu_put(policy); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| -static int cpufreq_stats_create_table(struct cpufreq_policy *policy, |  | ||||||
| +static int cpufreq_stats_update_table(struct cpufreq_policy *policy, |  | ||||||
|  		struct cpufreq_frequency_table *table) |  | ||||||
|  { |  | ||||||
| -	unsigned int i, j, count = 0, ret = 0; |  | ||||||
| -	struct cpufreq_stats *stat; |  | ||||||
| -	struct cpufreq_policy *data; |  | ||||||
| +	unsigned int i, j, count = 0; |  | ||||||
|  	unsigned int alloc_size; |  | ||||||
|  	unsigned int cpu = policy->cpu; |  | ||||||
| -	if (per_cpu(cpufreq_stats_table, cpu)) |  | ||||||
| -		return -EBUSY; |  | ||||||
| -	stat = kzalloc(sizeof(struct cpufreq_stats), GFP_KERNEL); |  | ||||||
| -	if ((stat) == NULL) |  | ||||||
| -		return -ENOMEM; |  | ||||||
| - |  | ||||||
| -	data = cpufreq_cpu_get(cpu); |  | ||||||
| -	if (data == NULL) { |  | ||||||
| -		ret = -EINVAL; |  | ||||||
| -		goto error_get_fail; |  | ||||||
| -	} |  | ||||||
| - |  | ||||||
| -	ret = sysfs_create_group(&data->kobj, &stats_attr_group); |  | ||||||
| -	if (ret) |  | ||||||
| -		goto error_out; |  | ||||||
| - |  | ||||||
| -	stat->cpu = cpu; |  | ||||||
| -	per_cpu(cpufreq_stats_table, cpu) = stat; |  | ||||||
| +	struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, cpu); |  | ||||||
|   |  | ||||||
|  	for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) { |  | ||||||
|  		unsigned int freq = table[i].frequency; |  | ||||||
| @@ -223,40 +196,73 @@ static int cpufreq_stats_create_table(st |  | ||||||
|  		count++; |  | ||||||
|  	} |  | ||||||
|   |  | ||||||
| +	if (stat->max_state != count) { |  | ||||||
| +		stat->max_state = count; |  | ||||||
| +		kfree(stat->time_in_state); |  | ||||||
| +		stat->time_in_state = NULL; |  | ||||||
| +	} |  | ||||||
|  	alloc_size = count * sizeof(int) + count * sizeof(cputime64_t); |  | ||||||
| - |  | ||||||
|  #ifdef CONFIG_CPU_FREQ_STAT_DETAILS |  | ||||||
|  	alloc_size += count * count * sizeof(int); |  | ||||||
|  #endif |  | ||||||
| -	stat->max_state = count; |  | ||||||
| -	stat->time_in_state = kzalloc(alloc_size, GFP_KERNEL); |  | ||||||
| -	if (!stat->time_in_state) { |  | ||||||
| -		ret = -ENOMEM; |  | ||||||
| -		goto error_out; |  | ||||||
| -	} |  | ||||||
| -	stat->freq_table = (unsigned int *)(stat->time_in_state + count); |  | ||||||
| - |  | ||||||
| +	if (stat->time_in_state) { |  | ||||||
| +		memset(stat->time_in_state, 0, alloc_size); |  | ||||||
| +	} else { |  | ||||||
| +		stat->time_in_state = kzalloc(alloc_size, GFP_KERNEL); |  | ||||||
| +		if (!stat->time_in_state) |  | ||||||
| +			return -ENOMEM; |  | ||||||
| +		stat->freq_table = (unsigned int *)( |  | ||||||
| +				stat->time_in_state + count); |  | ||||||
|  #ifdef CONFIG_CPU_FREQ_STAT_DETAILS |  | ||||||
| -	stat->trans_table = stat->freq_table + count; |  | ||||||
| +		stat->trans_table = stat->freq_table + count; |  | ||||||
|  #endif |  | ||||||
| +	} |  | ||||||
| + |  | ||||||
|  	j = 0; |  | ||||||
| -	for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) { |  | ||||||
| -		unsigned int freq = table[i].frequency; |  | ||||||
| -		if (freq == CPUFREQ_ENTRY_INVALID) |  | ||||||
| -			continue; |  | ||||||
| -		if (freq_table_get_index(stat, freq) == -1) |  | ||||||
| -			stat->freq_table[j++] = freq; |  | ||||||
| +	if (stat->freq_table) { |  | ||||||
| +		for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) { |  | ||||||
| +			unsigned int freq = table[i].frequency; |  | ||||||
| +			if (freq == CPUFREQ_ENTRY_INVALID) |  | ||||||
| +				continue; |  | ||||||
| +			if (freq_table_get_index(stat, freq) == -1) |  | ||||||
| +				stat->freq_table[j++] = freq; |  | ||||||
| +		} |  | ||||||
|  	} |  | ||||||
|  	stat->state_num = j; |  | ||||||
|  	spin_lock(&cpufreq_stats_lock); |  | ||||||
|  	stat->last_time = get_jiffies_64(); |  | ||||||
|  	stat->last_index = freq_table_get_index(stat, policy->cur); |  | ||||||
|  	spin_unlock(&cpufreq_stats_lock); |  | ||||||
| +	return 0; |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static int cpufreq_stats_create_table(struct cpufreq_policy *policy, |  | ||||||
| +		struct cpufreq_frequency_table *table) |  | ||||||
| +{ |  | ||||||
| +	unsigned int ret = 0; |  | ||||||
| +	struct cpufreq_stats *stat; |  | ||||||
| +	struct cpufreq_policy *data; |  | ||||||
| +	unsigned int cpu = policy->cpu; |  | ||||||
| + |  | ||||||
| +	stat = kzalloc(sizeof(struct cpufreq_stats), GFP_KERNEL); |  | ||||||
| +	if ((stat) == NULL) |  | ||||||
| +		return -ENOMEM; |  | ||||||
| + |  | ||||||
| +	data = cpufreq_cpu_get(cpu); |  | ||||||
| +	if (data == NULL) { |  | ||||||
| +		ret = -EINVAL; |  | ||||||
| +		goto error_out; |  | ||||||
| +	} |  | ||||||
| +	ret = sysfs_create_group(&data->kobj, &stats_attr_group); |  | ||||||
|  	cpufreq_cpu_put(data); |  | ||||||
| +	if (ret) |  | ||||||
| +		goto error_out; |  | ||||||
| + |  | ||||||
| +	stat->cpu = cpu; |  | ||||||
| +	per_cpu(cpufreq_stats_table, cpu) = stat; |  | ||||||
| + |  | ||||||
|  	return 0; |  | ||||||
|  error_out: |  | ||||||
| -	cpufreq_cpu_put(data); |  | ||||||
| -error_get_fail: |  | ||||||
|  	kfree(stat); |  | ||||||
|  	per_cpu(cpufreq_stats_table, cpu) = NULL; |  | ||||||
|  	return ret; |  | ||||||
| @@ -274,10 +280,12 @@ static int cpufreq_stat_notifier_policy( |  | ||||||
|  	table = cpufreq_frequency_get_table(cpu); |  | ||||||
|  	if (!table) |  | ||||||
|  		return 0; |  | ||||||
| -	ret = cpufreq_stats_create_table(policy, table); |  | ||||||
| -	if (ret) |  | ||||||
| -		return ret; |  | ||||||
| -	return 0; |  | ||||||
| +	if (!per_cpu(cpufreq_stats_table, cpu)) { |  | ||||||
| +		ret = cpufreq_stats_create_table(policy, table); |  | ||||||
| +		if (ret) |  | ||||||
| +			return ret; |  | ||||||
| +	} |  | ||||||
| +	return cpufreq_stats_update_table(policy, table); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
|  static int cpufreq_stat_notifier_trans(struct notifier_block *nb, |  | ||||||
| @@ -297,21 +305,23 @@ static int cpufreq_stat_notifier_trans(s |  | ||||||
|  	old_index = stat->last_index; |  | ||||||
|  	new_index = freq_table_get_index(stat, freq->new); |  | ||||||
|   |  | ||||||
| -	/* We can't do stat->time_in_state[-1]= .. */ |  | ||||||
| -	if (old_index == -1 || new_index == -1) |  | ||||||
| -		return 0; |  | ||||||
| - |  | ||||||
|  	cpufreq_stats_update(freq->cpu); |  | ||||||
| - |  | ||||||
|  	if (old_index == new_index) |  | ||||||
|  		return 0; |  | ||||||
|   |  | ||||||
| +	if (new_index == -1) |  | ||||||
| +		return 0; |  | ||||||
| + |  | ||||||
|  	spin_lock(&cpufreq_stats_lock); |  | ||||||
|  	stat->last_index = new_index; |  | ||||||
| +	if (old_index != -1) { |  | ||||||
|  #ifdef CONFIG_CPU_FREQ_STAT_DETAILS |  | ||||||
| -	stat->trans_table[old_index * stat->max_state + new_index]++; |  | ||||||
| +		if (stat->trans_table) |  | ||||||
| +			stat->trans_table[old_index * stat->max_state + |  | ||||||
| +					  new_index]++; |  | ||||||
|  #endif |  | ||||||
| -	stat->total_trans++; |  | ||||||
| +		stat->total_trans++; |  | ||||||
| +	} |  | ||||||
|  	spin_unlock(&cpufreq_stats_lock); |  | ||||||
|  	return 0; |  | ||||||
|  } |  | ||||||
| @@ -327,9 +337,6 @@ static int __cpuinit cpufreq_stat_cpu_ca |  | ||||||
|  	case CPU_ONLINE_FROZEN: |  | ||||||
|  		cpufreq_update_policy(cpu); |  | ||||||
|  		break; |  | ||||||
| -	case CPU_DOWN_PREPARE: |  | ||||||
| -		cpufreq_stats_free_sysfs(cpu); |  | ||||||
| -		break; |  | ||||||
|  	case CPU_DEAD: |  | ||||||
|  	case CPU_DEAD_FROZEN: |  | ||||||
|  		cpufreq_stats_free_table(cpu); |  | ||||||
| @@ -338,10 +345,9 @@ static int __cpuinit cpufreq_stat_cpu_ca |  | ||||||
|  	return NOTIFY_OK; |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| -/* priority=1 so this will get called before cpufreq_remove_dev */ |  | ||||||
| -static struct notifier_block cpufreq_stat_cpu_notifier __refdata = { |  | ||||||
| +static struct notifier_block cpufreq_stat_cpu_notifier __refdata = |  | ||||||
| +{ |  | ||||||
|  	.notifier_call = cpufreq_stat_cpu_callback, |  | ||||||
| -	.priority = 1, |  | ||||||
|  }; |  | ||||||
|   |  | ||||||
|  static struct notifier_block notifier_policy_block = { |  | ||||||
| @@ -388,7 +394,6 @@ static void __exit cpufreq_stats_exit(vo |  | ||||||
|  	unregister_hotcpu_notifier(&cpufreq_stat_cpu_notifier); |  | ||||||
|  	for_each_online_cpu(cpu) { |  | ||||||
|  		cpufreq_stats_free_table(cpu); |  | ||||||
| -		cpufreq_stats_free_sysfs(cpu); |  | ||||||
|  	} |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| @@ -1,351 +0,0 @@ | |||||||
| From 27ff621cd9a5347efda4be502abbef13a99146ce Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Maarten ter Huurne <maarten@treewalker.org> |  | ||||||
| Date: Sun, 29 Aug 2010 08:11:00 +0200 |  | ||||||
| Subject: [PATCH 11/21] MIPS: JZ4740: Added setting of PLL rate and main |  | ||||||
|  dividers. |  | ||||||
|  |  | ||||||
| This functionality makes a cpufreq driver possible. |  | ||||||
| Squashed version of the development done in the jz-2.6.39 branch. |  | ||||||
| --- |  | ||||||
|  arch/mips/jz4740/clock.c |  230 ++++++++++++++++++++++++++++++++++++++++++++-- |  | ||||||
|  arch/mips/jz4740/clock.h |    4 + |  | ||||||
|  2 files changed, 224 insertions(+), 10 deletions(-) |  | ||||||
|  |  | ||||||
| --- a/arch/mips/jz4740/clock.c |  | ||||||
| +++ b/arch/mips/jz4740/clock.c |  | ||||||
| @@ -1,5 +1,8 @@ |  | ||||||
|  /* |  | ||||||
| + *  Copyright (c) 2006-2007, Ingenic Semiconductor Inc. |  | ||||||
|   *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de> |  | ||||||
| + *  Copyright (c) 2010, Ulrich Hecht <ulrich.hecht@gmail.com> |  | ||||||
| + *  Copyright (c) 2010, Maarten ter Huurne <maarten@treewalker.org> |  | ||||||
|   *  JZ4740 SoC clock support |  | ||||||
|   * |  | ||||||
|   *  This program is free software; you can redistribute it and/or modify it |  | ||||||
| @@ -41,16 +44,20 @@ |  | ||||||
|  #define JZ_CLOCK_CTRL_I2S_SRC_PLL	BIT(31) |  | ||||||
|  #define JZ_CLOCK_CTRL_KO_ENABLE		BIT(30) |  | ||||||
|  #define JZ_CLOCK_CTRL_UDC_SRC_PLL	BIT(29) |  | ||||||
| -#define JZ_CLOCK_CTRL_UDIV_MASK		0x1f800000 |  | ||||||
|  #define JZ_CLOCK_CTRL_CHANGE_ENABLE	BIT(22) |  | ||||||
|  #define JZ_CLOCK_CTRL_PLL_HALF		BIT(21) |  | ||||||
| -#define JZ_CLOCK_CTRL_LDIV_MASK		0x001f0000 |  | ||||||
|  #define JZ_CLOCK_CTRL_UDIV_OFFSET	23 |  | ||||||
|  #define JZ_CLOCK_CTRL_LDIV_OFFSET	16 |  | ||||||
|  #define JZ_CLOCK_CTRL_MDIV_OFFSET	12 |  | ||||||
|  #define JZ_CLOCK_CTRL_PDIV_OFFSET	 8 |  | ||||||
|  #define JZ_CLOCK_CTRL_HDIV_OFFSET	 4 |  | ||||||
|  #define JZ_CLOCK_CTRL_CDIV_OFFSET	 0 |  | ||||||
| +#define JZ_CLOCK_CTRL_UDIV_MASK		(0x3f << JZ_CLOCK_CTRL_UDIV_OFFSET) |  | ||||||
| +#define JZ_CLOCK_CTRL_LDIV_MASK		(0x1f << JZ_CLOCK_CTRL_LDIV_OFFSET) |  | ||||||
| +#define JZ_CLOCK_CTRL_MDIV_MASK		(0x0f << JZ_CLOCK_CTRL_MDIV_OFFSET) |  | ||||||
| +#define JZ_CLOCK_CTRL_PDIV_MASK		(0x0f << JZ_CLOCK_CTRL_PDIV_OFFSET) |  | ||||||
| +#define JZ_CLOCK_CTRL_HDIV_MASK		(0x0f << JZ_CLOCK_CTRL_HDIV_OFFSET) |  | ||||||
| +#define JZ_CLOCK_CTRL_CDIV_MASK		(0x0f << JZ_CLOCK_CTRL_CDIV_OFFSET) |  | ||||||
|   |  | ||||||
|  #define JZ_CLOCK_GATE_UART0	BIT(0) |  | ||||||
|  #define JZ_CLOCK_GATE_TCU	BIT(1) |  | ||||||
| @@ -90,6 +97,7 @@ |  | ||||||
|  #define JZ_CLOCK_PLL_M_OFFSET		23 |  | ||||||
|  #define JZ_CLOCK_PLL_N_OFFSET		18 |  | ||||||
|  #define JZ_CLOCK_PLL_OD_OFFSET		16 |  | ||||||
| +#define JZ_CLOCK_PLL_STABILIZE_OFFSET	0 |  | ||||||
|   |  | ||||||
|  #define JZ_CLOCK_LOW_POWER_MODE_DOZE BIT(2) |  | ||||||
|  #define JZ_CLOCK_LOW_POWER_MODE_SLEEP BIT(0) |  | ||||||
| @@ -97,10 +105,15 @@ |  | ||||||
|  #define JZ_CLOCK_SLEEP_CTRL_SUSPEND_UHC BIT(7) |  | ||||||
|  #define JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC BIT(6) |  | ||||||
|   |  | ||||||
| +#define JZ_REG_EMC_RTCNT	0x88 |  | ||||||
| +#define JZ_REG_EMC_RTCOR	0x8C |  | ||||||
| + |  | ||||||
|  static void __iomem *jz_clock_base; |  | ||||||
|  static spinlock_t jz_clock_lock; |  | ||||||
|  static LIST_HEAD(jz_clocks); |  | ||||||
|   |  | ||||||
| +static void __iomem *jz_emc_base; |  | ||||||
| + |  | ||||||
|  struct main_clk { |  | ||||||
|  	struct clk clk; |  | ||||||
|  	uint32_t div_offset; |  | ||||||
| @@ -204,25 +217,88 @@ static int jz_clk_ko_is_enabled(struct c |  | ||||||
|  	return !!(jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_KO_ENABLE); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| +static struct static_clk jz_clk_ext; |  | ||||||
| + |  | ||||||
| +static unsigned long jz_clk_pll_calc_rate( |  | ||||||
| +	unsigned int in_div, unsigned int feedback, unsigned int out_div) |  | ||||||
| +{ |  | ||||||
| +	return ((jz_clk_ext.rate / in_div) * feedback) / out_div; |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static void jz_clk_pll_calc_dividers(unsigned long rate, |  | ||||||
| +	unsigned int *in_div, unsigned int *feedback, unsigned int *out_div) |  | ||||||
| +{ |  | ||||||
| +	unsigned int target; |  | ||||||
| + |  | ||||||
| +	/* The frequency after the input divider must be between 1 and 15 MHz. |  | ||||||
| +	   The highest divider yields the best resolution. */ |  | ||||||
| +	*in_div = jz_clk_ext.rate / 1000000; |  | ||||||
| +	if (*in_div >= 34) |  | ||||||
| +		*in_div = 33; |  | ||||||
| + |  | ||||||
| +	/* The frequency before the output divider must be between 100 and |  | ||||||
| +	   500 MHz. The lowest target rate is more energy efficient. */ |  | ||||||
| +	if (rate < 25000000) { |  | ||||||
| +		*out_div = 4; |  | ||||||
| +		target = 25000000 * 4; |  | ||||||
| +	} else if (rate <= 50000000) { |  | ||||||
| +		*out_div = 4; |  | ||||||
| +		target = rate * 4; |  | ||||||
| +	} else if (rate <= 100000000) { |  | ||||||
| +		*out_div = 2; |  | ||||||
| +		target = rate * 2; |  | ||||||
| +	} else if (rate <= 500000000) { |  | ||||||
| +		*out_div = 1; |  | ||||||
| +		target = rate; |  | ||||||
| +	} else { |  | ||||||
| +		*out_div = 1; |  | ||||||
| +		target = 500000000; |  | ||||||
| +	} |  | ||||||
| + |  | ||||||
| +	/* Compute the feedback divider. |  | ||||||
| +	   Since the divided input is at least 1 MHz and the target frequency |  | ||||||
| +	   at most 500 MHz, the feedback will be at most 500 and will therefore |  | ||||||
| +	   always fit in the 9-bit register. |  | ||||||
| +	   Similarly, the divided input is at most 15 MHz and the target |  | ||||||
| +	   frequency at least 100 MHz, so the feedback will be at least 6 |  | ||||||
| +	   where the minimum supported value is 2. */ |  | ||||||
| +	*feedback = ((target / 1000) * *in_div) / (jz_clk_ext.rate / 1000); |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static unsigned long jz_clk_pll_round_rate(struct clk *clk, unsigned long rate) |  | ||||||
| +{ |  | ||||||
| +	unsigned int in_div, feedback, out_div; |  | ||||||
| +	/* The PLL frequency must be a multiple of 24 MHz, since the LCD pixel |  | ||||||
| +	 * clock must be exactly 12 MHz for the TV-out to work. |  | ||||||
| +	 * TODO: A multiple of 12 MHz for the PLL would work if the PLL would |  | ||||||
| +	 *       not be divided by 2 before being passed to the set of derived |  | ||||||
| +	 *       clocks that includes the LCD pixel clock. |  | ||||||
| +	 * TODO: Systemwide decisions like this should be made by the board |  | ||||||
| +	 *       support code, so add some kind of hook for that. |  | ||||||
| +	 */ |  | ||||||
| +	unsigned long rate24 = (rate / 24000000) * 24000000; |  | ||||||
| + |  | ||||||
| +	jz_clk_pll_calc_dividers(rate24, &in_div, &feedback, &out_div); |  | ||||||
| +	return jz_clk_pll_calc_rate(in_div, feedback, out_div); |  | ||||||
| +} |  | ||||||
| + |  | ||||||
|  static const int pllno[] = {1, 2, 2, 4}; |  | ||||||
|   |  | ||||||
|  static unsigned long jz_clk_pll_get_rate(struct clk *clk) |  | ||||||
|  { |  | ||||||
|  	uint32_t val; |  | ||||||
| -	int m; |  | ||||||
| -	int n; |  | ||||||
| -	int od; |  | ||||||
| +	unsigned int in_div, feedback, out_div; |  | ||||||
|   |  | ||||||
|  	val = jz_clk_reg_read(JZ_REG_CLOCK_PLL); |  | ||||||
|   |  | ||||||
|  	if (val & JZ_CLOCK_PLL_BYPASS) |  | ||||||
|  		return clk_get_rate(clk->parent); |  | ||||||
|   |  | ||||||
| -	m = ((val >> 23) & 0x1ff) + 2; |  | ||||||
| -	n = ((val >> 18) & 0x1f) + 2; |  | ||||||
| -	od = (val >> 16) & 0x3; |  | ||||||
| +	feedback = ((val >> 23) & 0x1ff) + 2; |  | ||||||
| +	in_div = ((val >> 18) & 0x1f) + 2; |  | ||||||
| +	out_div = pllno[(val >> 16) & 0x3]; |  | ||||||
|   |  | ||||||
| -	return ((clk_get_rate(clk->parent) / n) * m) / pllno[od]; |  | ||||||
| +	return jz_clk_pll_calc_rate(in_div, feedback, out_div); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
|  static unsigned long jz_clk_pll_half_get_rate(struct clk *clk) |  | ||||||
| @@ -235,7 +311,77 @@ static unsigned long jz_clk_pll_half_get |  | ||||||
|  	return jz_clk_pll_get_rate(clk->parent) >> 1; |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| -static const int jz_clk_main_divs[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; |  | ||||||
| +#define SDRAM_TREF 15625   /* Refresh period: 4096 refresh cycles/64ms */ |  | ||||||
| + |  | ||||||
| +static void sdram_set_pll(unsigned int pllin) |  | ||||||
| +{ |  | ||||||
| +	unsigned int ns, sdramclock; |  | ||||||
| + |  | ||||||
| +	ns = 1000000000 / pllin; |  | ||||||
| +	sdramclock = (SDRAM_TREF / ns) / 64 + 1; |  | ||||||
| +	if (sdramclock > 0xff) sdramclock = 0xff; |  | ||||||
| +	/* Set refresh registers */ |  | ||||||
| +	writew(sdramclock, jz_emc_base + JZ_REG_EMC_RTCOR); |  | ||||||
| +	writew(sdramclock, jz_emc_base + JZ_REG_EMC_RTCNT); |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static int jz_clk_pll_set_rate(struct clk *clk, unsigned long rate) |  | ||||||
| +{ |  | ||||||
| +	unsigned int ctrl, plcr1; |  | ||||||
| +	unsigned int feedback, in_div, out_div, pllout, pllout2; |  | ||||||
| + |  | ||||||
| +	jz_clk_pll_calc_dividers(rate, &in_div, &feedback, &out_div); |  | ||||||
| + |  | ||||||
| +	ctrl = jz_clk_reg_read(JZ_REG_CLOCK_CTRL); |  | ||||||
| +	pllout = jz_clk_pll_calc_rate(in_div, feedback, out_div); |  | ||||||
| +	pllout2 = (ctrl & JZ_CLOCK_CTRL_PLL_HALF) ? pllout : (pllout / 2); |  | ||||||
| + |  | ||||||
| +	/* Init UHC clock */ |  | ||||||
| +	writel(pllout2 / 48000000 - 1, jz_clock_base + JZ_REG_CLOCK_UHC); |  | ||||||
| + |  | ||||||
| +	plcr1 = ((feedback - 2) << JZ_CLOCK_PLL_M_OFFSET) | |  | ||||||
| +		((in_div - 2) << JZ_CLOCK_PLL_N_OFFSET) | |  | ||||||
| +		((out_div - 1) << JZ_CLOCK_PLL_OD_OFFSET) | |  | ||||||
| +		(0x20 << JZ_CLOCK_PLL_STABILIZE_OFFSET) | |  | ||||||
| +		JZ_CLOCK_PLL_ENABLED; |  | ||||||
| + |  | ||||||
| +	sdram_set_pll(pllout); |  | ||||||
| + |  | ||||||
| +	/* LCD pixclock */ |  | ||||||
| +	writel(pllout2 / 12000000 - 1, jz_clock_base + JZ_REG_CLOCK_LCD); |  | ||||||
| + |  | ||||||
| +	/* configure PLL */ |  | ||||||
| +	__asm__ __volatile__( |  | ||||||
| +		".set noreorder\n\t" |  | ||||||
| +		".align 5\n" |  | ||||||
| +		"sw %1,0(%0)\n\t" |  | ||||||
| +		"nop\n\t" |  | ||||||
| +		"nop\n\t" |  | ||||||
| +		"nop\n\t" |  | ||||||
| +		"nop\n\t" |  | ||||||
| +		"nop\n\t" |  | ||||||
| +		"nop\n\t" |  | ||||||
| +		"nop\n\t" |  | ||||||
| +		".set reorder\n\t" |  | ||||||
| +		: |  | ||||||
| +		: "r" (jz_clock_base + JZ_REG_CLOCK_PLL), "r" (plcr1)); |  | ||||||
| + |  | ||||||
| +	/* MtH: For some reason the MSC will have problems if this flag is not |  | ||||||
| +	        restored, even though the MSC is supposedly the only divider |  | ||||||
| +	        that is not affected by this flag. */ |  | ||||||
| +	jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_CHANGE_ENABLE); |  | ||||||
| + |  | ||||||
| +	return 0; |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static const unsigned int jz_clk_main_divs[] = { |  | ||||||
| +	1, 2, 3, 4, 6, 8, 12, 16, 24, 32 |  | ||||||
| +}; |  | ||||||
| +static const unsigned int jz_clk_main_divs_inv[] = { |  | ||||||
| +	-1,  0,  1,  2,  3, -1,  4, -1,  5, -1, -1, -1,  6, -1, -1, -1, |  | ||||||
| +	 7, -1, -1, -1, -1, -1, -1, -1,  8, -1, -1, -1, -1, -1, -1, -1, |  | ||||||
| +	 9 |  | ||||||
| +}; |  | ||||||
|   |  | ||||||
|  static unsigned long jz_clk_main_round_rate(struct clk *clk, unsigned long rate) |  | ||||||
|  { |  | ||||||
| @@ -290,6 +436,64 @@ static int jz_clk_main_set_rate(struct c |  | ||||||
|  	return 0; |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| +static struct main_clk jz_clk_cpu; |  | ||||||
| + |  | ||||||
| +int clk_main_set_dividers(bool immediate, unsigned int cdiv, unsigned int hdiv, |  | ||||||
| +			  unsigned int mdiv, unsigned int pdiv) |  | ||||||
| +{ |  | ||||||
| +	unsigned int cdiv_enc, hdiv_enc, mdiv_enc, pdiv_enc; |  | ||||||
| +	unsigned int ctrl; |  | ||||||
| +	unsigned int tmp, wait; |  | ||||||
| + |  | ||||||
| +	if (cdiv >= ARRAY_SIZE(jz_clk_main_divs_inv) || |  | ||||||
| +	    hdiv >= ARRAY_SIZE(jz_clk_main_divs_inv) || |  | ||||||
| +	    mdiv >= ARRAY_SIZE(jz_clk_main_divs_inv) || |  | ||||||
| +	    pdiv >= ARRAY_SIZE(jz_clk_main_divs_inv)) |  | ||||||
| +		return -EINVAL; |  | ||||||
| +	cdiv_enc = jz_clk_main_divs_inv[cdiv]; |  | ||||||
| +	hdiv_enc = jz_clk_main_divs_inv[hdiv]; |  | ||||||
| +	mdiv_enc = jz_clk_main_divs_inv[mdiv]; |  | ||||||
| +	pdiv_enc = jz_clk_main_divs_inv[pdiv]; |  | ||||||
| +	if (cdiv_enc == (unsigned int)-1 || |  | ||||||
| +	    hdiv_enc == (unsigned int)-1 || |  | ||||||
| +	    mdiv_enc == (unsigned int)-1 || |  | ||||||
| +	    pdiv_enc == (unsigned int)-1) |  | ||||||
| +		return -EINVAL; |  | ||||||
| + |  | ||||||
| +	ctrl = jz_clk_reg_read(JZ_REG_CLOCK_CTRL); |  | ||||||
| +	ctrl &= ~(JZ_CLOCK_CTRL_CHANGE_ENABLE | |  | ||||||
| +		  JZ_CLOCK_CTRL_CDIV_MASK | JZ_CLOCK_CTRL_HDIV_MASK | |  | ||||||
| +		  JZ_CLOCK_CTRL_MDIV_MASK | JZ_CLOCK_CTRL_PDIV_MASK); |  | ||||||
| +	if (immediate) ctrl |= JZ_CLOCK_CTRL_CHANGE_ENABLE; |  | ||||||
| +	ctrl |= (cdiv_enc << JZ_CLOCK_CTRL_CDIV_OFFSET) | |  | ||||||
| +		(hdiv_enc << JZ_CLOCK_CTRL_HDIV_OFFSET) | |  | ||||||
| +		(mdiv_enc << JZ_CLOCK_CTRL_MDIV_OFFSET) | |  | ||||||
| +		(pdiv_enc << JZ_CLOCK_CTRL_PDIV_OFFSET); |  | ||||||
| + |  | ||||||
| +	/* set dividers */ |  | ||||||
| +	/* delay loops lifted from the old Ingenic cpufreq driver */ |  | ||||||
| +	wait = ((clk_get_rate(&jz_clk_cpu.clk) / 1000000) * 500) / 1000; |  | ||||||
| +	__asm__ __volatile__( |  | ||||||
| +		".set noreorder\n\t" |  | ||||||
| +		".align 5\n" |  | ||||||
| +		"sw %2,0(%1)\n\t" |  | ||||||
| +		"li %0,0\n\t" |  | ||||||
| +		"1:\n\t" |  | ||||||
| +		"bne %0,%3,1b\n\t" |  | ||||||
| +		"addi %0, 1\n\t" |  | ||||||
| +		"nop\n\t" |  | ||||||
| +		"nop\n\t" |  | ||||||
| +		"nop\n\t" |  | ||||||
| +		"nop\n\t" |  | ||||||
| +		".set reorder\n\t" |  | ||||||
| +		: "=r" (tmp) |  | ||||||
| +		: "r" (jz_clock_base + JZ_REG_CLOCK_CTRL), "r" (ctrl), |  | ||||||
| +		  "r" (wait)); |  | ||||||
| + |  | ||||||
| +	return 0; |  | ||||||
| +} |  | ||||||
| +EXPORT_SYMBOL_GPL(clk_main_set_dividers); |  | ||||||
| + |  | ||||||
|  static struct clk_ops jz_clk_static_ops = { |  | ||||||
|  	.get_rate = jz_clk_static_get_rate, |  | ||||||
|  	.enable = jz_clk_enable_gating, |  | ||||||
| @@ -307,6 +511,8 @@ static struct static_clk jz_clk_ext = { |  | ||||||
|   |  | ||||||
|  static struct clk_ops jz_clk_pll_ops = { |  | ||||||
|  	.get_rate = jz_clk_pll_get_rate, |  | ||||||
| +	.set_rate = jz_clk_pll_set_rate, |  | ||||||
| +	.round_rate = jz_clk_pll_round_rate, |  | ||||||
|  }; |  | ||||||
|   |  | ||||||
|  static struct clk jz_clk_pll = { |  | ||||||
| @@ -897,6 +1103,10 @@ static int jz4740_clock_init(void) |  | ||||||
|  	if (!jz_clock_base) |  | ||||||
|  		return -EBUSY; |  | ||||||
|   |  | ||||||
| +	jz_emc_base = ioremap(JZ4740_EMC_BASE_ADDR, 0x100); |  | ||||||
| +	if (!jz_emc_base) |  | ||||||
| +		return -EBUSY; |  | ||||||
| + |  | ||||||
|  	spin_lock_init(&jz_clock_lock); |  | ||||||
|   |  | ||||||
|  	jz_clk_ext.rate = jz4740_clock_bdata.ext_rate; |  | ||||||
| --- a/arch/mips/jz4740/clock.h |  | ||||||
| +++ b/arch/mips/jz4740/clock.h |  | ||||||
| @@ -17,6 +17,7 @@ |  | ||||||
|  #define __MIPS_JZ4740_CLOCK_H__ |  | ||||||
|   |  | ||||||
|  #include <linux/list.h> |  | ||||||
| +#include <linux/types.h> |  | ||||||
|   |  | ||||||
|  struct jz4740_clock_board_data { |  | ||||||
|  	unsigned long ext_rate; |  | ||||||
| @@ -63,6 +64,9 @@ struct clk { |  | ||||||
|   |  | ||||||
|  int clk_is_enabled(struct clk *clk); |  | ||||||
|   |  | ||||||
| +int clk_main_set_dividers(bool immediate, unsigned int cdiv, unsigned int hdiv, |  | ||||||
| +			  unsigned int mdiv, unsigned int pdiv); |  | ||||||
| + |  | ||||||
|  #ifdef CONFIG_DEBUG_FS |  | ||||||
|  void jz4740_clock_debugfs_init(void); |  | ||||||
|  void jz4740_clock_debugfs_add_clk(struct clk *clk); |  | ||||||
| @@ -1,298 +0,0 @@ | |||||||
| From d0f0d5739a31c12d349980ed05a670fa1e84696d Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Maarten ter Huurne <maarten@treewalker.org> |  | ||||||
| Date: Wed, 16 Mar 2011 03:16:04 +0100 |  | ||||||
| Subject: [PATCH 12/21] MIPS: JZ4740: Add cpufreq support. |  | ||||||
|  |  | ||||||
| This is a squashed version of Uli's driver that was further developed in the opendingux-kernel repository. |  | ||||||
| --- |  | ||||||
|  arch/mips/Kconfig                |    1 + |  | ||||||
|  arch/mips/jz4740/Makefile        |    1 + |  | ||||||
|  arch/mips/jz4740/cpufreq.c       |  226 ++++++++++++++++++++++++++++++++++++++ |  | ||||||
|  arch/mips/kernel/cpufreq/Kconfig |   13 ++- |  | ||||||
|  4 files changed, 240 insertions(+), 1 deletions(-) |  | ||||||
|  create mode 100644 arch/mips/jz4740/cpufreq.c |  | ||||||
|  |  | ||||||
| --- a/arch/mips/Kconfig |  | ||||||
| +++ b/arch/mips/Kconfig |  | ||||||
| @@ -212,6 +212,7 @@ config MACH_JZ4740 |  | ||||||
|  	select HAVE_PWM |  | ||||||
|  	select HAVE_CLK |  | ||||||
|  	select GENERIC_IRQ_CHIP |  | ||||||
| +	select CPU_SUPPORTS_CPUFREQ |  | ||||||
|   |  | ||||||
|  config LANTIQ |  | ||||||
|  	bool "Lantiq based platforms" |  | ||||||
| --- a/arch/mips/jz4740/Makefile |  | ||||||
| +++ b/arch/mips/jz4740/Makefile |  | ||||||
| @@ -16,5 +16,6 @@ obj-$(CONFIG_JZ4740_QI_LB60)	+= board-qi |  | ||||||
|  # PM support |  | ||||||
|   |  | ||||||
|  obj-$(CONFIG_PM) += pm.o |  | ||||||
| +obj-$(CONFIG_CPU_FREQ_JZ) += cpufreq.o |  | ||||||
|   |  | ||||||
|  ccflags-y := -Werror -Wall |  | ||||||
| --- /dev/null |  | ||||||
| +++ b/arch/mips/jz4740/cpufreq.c |  | ||||||
| @@ -0,0 +1,226 @@ |  | ||||||
| +/* |  | ||||||
| + * linux/arch/mips/jz4740/cpufreq.c |  | ||||||
| + * |  | ||||||
| + * cpufreq driver for JZ4740 |  | ||||||
| + * |  | ||||||
| + * Copyright (c) 2010       Ulrich Hecht <ulrich.hecht@gmail.com> |  | ||||||
| + * Copyright (c) 2010       Maarten ter Huurne <maarten@treewalker.org> |  | ||||||
| + * |  | ||||||
| + * 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. |  | ||||||
| + */ |  | ||||||
| + |  | ||||||
| +#include <linux/kernel.h> |  | ||||||
| +#include <linux/module.h> |  | ||||||
| +#include <linux/init.h> |  | ||||||
| +#include <linux/err.h> |  | ||||||
| + |  | ||||||
| +#include <linux/cpufreq.h> |  | ||||||
| + |  | ||||||
| +#include <linux/clk.h> |  | ||||||
| +#include <asm/mach-jz4740/base.h> |  | ||||||
| + |  | ||||||
| +#include "clock.h" |  | ||||||
| + |  | ||||||
| +#define DEBUG_CPUFREQ |  | ||||||
| + |  | ||||||
| +#ifdef DEBUG_CPUFREQ |  | ||||||
| +#define dprintk(X...) printk(KERN_INFO X) |  | ||||||
| +#else |  | ||||||
| +#define dprintk(X...) do { } while(0) |  | ||||||
| +#endif |  | ||||||
| + |  | ||||||
| +#define HCLK_MIN 30000 |  | ||||||
| +/* TODO: The maximum MCLK most likely depends on the SDRAM chips used, |  | ||||||
| +         so it is board-specific. */ |  | ||||||
| +#define MCLK_MAX 140000 |  | ||||||
| + |  | ||||||
| +/* Same as jz_clk_main_divs, but with 24 and 32 removed because the hardware |  | ||||||
| +   spec states those dividers must not be used for CCLK or HCLK. */ |  | ||||||
| +static const unsigned int jz4740_freq_cpu_divs[] = {1, 2, 3, 4, 6, 8, 12, 16}; |  | ||||||
| + |  | ||||||
| +struct jz4740_freq_percpu_info { |  | ||||||
| +	unsigned int pll_rate; |  | ||||||
| +	struct cpufreq_frequency_table table[ |  | ||||||
| +		ARRAY_SIZE(jz4740_freq_cpu_divs) + 1]; |  | ||||||
| +}; |  | ||||||
| + |  | ||||||
| +static struct clk *pll; |  | ||||||
| +static struct clk *cclk; |  | ||||||
| + |  | ||||||
| +static struct jz4740_freq_percpu_info jz4740_freq_info; |  | ||||||
| + |  | ||||||
| +static struct cpufreq_driver cpufreq_jz4740_driver; |  | ||||||
| + |  | ||||||
| +static void jz4740_freq_fill_table(struct cpufreq_policy *policy, |  | ||||||
| +				   unsigned int pll_rate) |  | ||||||
| +{ |  | ||||||
| +	struct cpufreq_frequency_table *table = &jz4740_freq_info.table[0]; |  | ||||||
| +	int i; |  | ||||||
| + |  | ||||||
| +#ifdef CONFIG_CPU_FREQ_STAT_DETAILS |  | ||||||
| +	/* for showing /sys/devices/system/cpu/cpuX/cpufreq/stats/ */ |  | ||||||
| +	static bool init = false; |  | ||||||
| +	if (init) |  | ||||||
| +		cpufreq_frequency_table_put_attr(policy->cpu); |  | ||||||
| +	else |  | ||||||
| +		init = true; |  | ||||||
| +#endif |  | ||||||
| + |  | ||||||
| +	jz4740_freq_info.pll_rate = pll_rate; |  | ||||||
| + |  | ||||||
| +	for (i = 0; i < ARRAY_SIZE(jz4740_freq_cpu_divs); i++) { |  | ||||||
| +		unsigned int freq = pll_rate / jz4740_freq_cpu_divs[i]; |  | ||||||
| +		if (freq < HCLK_MIN) break; |  | ||||||
| +		table[i].index = i; |  | ||||||
| +		table[i].frequency = freq; |  | ||||||
| +	} |  | ||||||
| +	table[i].index = i; |  | ||||||
| +	table[i].frequency = CPUFREQ_TABLE_END; |  | ||||||
| + |  | ||||||
| +	policy->min = table[i - 1].frequency; |  | ||||||
| +	policy->max = table[0].frequency; |  | ||||||
| + |  | ||||||
| +#ifdef CONFIG_CPU_FREQ_STAT_DETAILS |  | ||||||
| +	cpufreq_frequency_table_get_attr(table, policy->cpu); |  | ||||||
| +#endif |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static unsigned int jz4740_freq_get(unsigned int cpu) |  | ||||||
| +{ |  | ||||||
| +	return clk_get_rate(cclk) / 1000; |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static int jz4740_freq_verify(struct cpufreq_policy *policy) |  | ||||||
| +{ |  | ||||||
| +	unsigned int new_pll; |  | ||||||
| + |  | ||||||
| +	cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, |  | ||||||
| +				     policy->cpuinfo.max_freq); |  | ||||||
| + |  | ||||||
| +	new_pll = clk_round_rate(pll, policy->max * 1000) / 1000; |  | ||||||
| +	if (jz4740_freq_info.pll_rate != new_pll) |  | ||||||
| +		jz4740_freq_fill_table(policy, new_pll); |  | ||||||
| + |  | ||||||
| +	return 0; |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static int jz4740_freq_target(struct cpufreq_policy *policy, |  | ||||||
| +			  unsigned int target_freq, |  | ||||||
| +			  unsigned int relation) |  | ||||||
| +{ |  | ||||||
| +	struct cpufreq_frequency_table *table = &jz4740_freq_info.table[0]; |  | ||||||
| +	struct cpufreq_freqs freqs; |  | ||||||
| +	unsigned int new_index = 0; |  | ||||||
| +	unsigned int old_pll = clk_get_rate(pll) / 1000; |  | ||||||
| +	unsigned int new_pll = jz4740_freq_info.pll_rate; |  | ||||||
| +	int ret = 0; |  | ||||||
| + |  | ||||||
| +	if (cpufreq_frequency_table_target(policy, table, |  | ||||||
| +					   target_freq, relation, &new_index)) |  | ||||||
| +		return -EINVAL; |  | ||||||
| +	freqs = (struct cpufreq_freqs) { |  | ||||||
| +		.old = jz4740_freq_get(policy->cpu), |  | ||||||
| +		.new = table[new_index].frequency, |  | ||||||
| +		.cpu = policy->cpu, |  | ||||||
| +		.flags = cpufreq_jz4740_driver.flags, |  | ||||||
| +	}; |  | ||||||
| +	if (freqs.new != freqs.old || new_pll != old_pll) { |  | ||||||
| +		unsigned int cdiv, hdiv, mdiv, pdiv; |  | ||||||
| +		cdiv = jz4740_freq_cpu_divs[new_index]; |  | ||||||
| +		hdiv = (cdiv == 3 || cdiv == 6) ? cdiv * 2 : cdiv * 3; |  | ||||||
| +		while (new_pll < HCLK_MIN * hdiv) |  | ||||||
| +			hdiv -= cdiv; |  | ||||||
| +		mdiv = hdiv; |  | ||||||
| +		if (new_pll > MCLK_MAX * mdiv) { |  | ||||||
| +			/* 4,4 performs better than 3,6 */ |  | ||||||
| +			if (new_pll > MCLK_MAX * 4) |  | ||||||
| +				mdiv *= 2; |  | ||||||
| +			else |  | ||||||
| +				hdiv = mdiv = cdiv * 4; |  | ||||||
| +		} |  | ||||||
| +		pdiv = mdiv; |  | ||||||
| +		dprintk(KERN_INFO "%s: cclk %p, setting from %d to %d, " |  | ||||||
| +			"dividers %d, %d, %d, %d\n", |  | ||||||
| +			__FUNCTION__, cclk, freqs.old, freqs.new, |  | ||||||
| +			cdiv, hdiv, mdiv, pdiv); |  | ||||||
| +		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); |  | ||||||
| +		ret = clk_main_set_dividers(new_pll == old_pll, |  | ||||||
| +					    cdiv, hdiv, mdiv, pdiv); |  | ||||||
| +		if (ret) { |  | ||||||
| +			dprintk(KERN_INFO "failed to set dividers\n"); |  | ||||||
| +		} else if (new_pll != old_pll) { |  | ||||||
| +			dprintk(KERN_INFO "%s: pll %p, setting from %d to %d\n", |  | ||||||
| +				__FUNCTION__, pll, old_pll, new_pll); |  | ||||||
| +			ret = clk_set_rate(pll, new_pll * 1000); |  | ||||||
| +		} |  | ||||||
| +		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); |  | ||||||
| +	} |  | ||||||
| + |  | ||||||
| +	return ret; |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static int jz4740_cpufreq_driver_init(struct cpufreq_policy *policy) |  | ||||||
| +{ |  | ||||||
| +	int ret; |  | ||||||
| + |  | ||||||
| +	dprintk(KERN_INFO "Jz4740 cpufreq driver\n"); |  | ||||||
| + |  | ||||||
| +	if (policy->cpu != 0) |  | ||||||
| +		return -EINVAL; |  | ||||||
| + |  | ||||||
| +	pll = clk_get(NULL, "pll"); |  | ||||||
| +	if (IS_ERR(pll)) { |  | ||||||
| +		ret = PTR_ERR(pll); |  | ||||||
| +		goto err_exit; |  | ||||||
| +	} |  | ||||||
| + |  | ||||||
| +	cclk = clk_get(NULL, "cclk"); |  | ||||||
| +	if (IS_ERR(cclk)) { |  | ||||||
| +		ret = PTR_ERR(cclk); |  | ||||||
| +		goto err_clk_put_pll; |  | ||||||
| +	} |  | ||||||
| + |  | ||||||
| +	policy->cpuinfo.min_freq = HCLK_MIN; |  | ||||||
| +	policy->cpuinfo.max_freq = 500000; |  | ||||||
| +	policy->cpuinfo.transition_latency = 100000; /* in nanoseconds */ |  | ||||||
| +	policy->cur = jz4740_freq_get(policy->cpu); |  | ||||||
| +	policy->governor = CPUFREQ_DEFAULT_GOVERNOR; |  | ||||||
| +	/* min and max are set by jz4740_freq_fill_table() */ |  | ||||||
| + |  | ||||||
| +	jz4740_freq_fill_table(policy, clk_get_rate(pll) / 1000 /* in kHz */); |  | ||||||
| + |  | ||||||
| +	return 0; |  | ||||||
| + |  | ||||||
| +err_clk_put_pll: |  | ||||||
| +	clk_put(pll); |  | ||||||
| +err_exit: |  | ||||||
| +	return ret; |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static struct cpufreq_driver cpufreq_jz4740_driver = { |  | ||||||
| +	.init	= jz4740_cpufreq_driver_init, |  | ||||||
| +	.verify	= jz4740_freq_verify, |  | ||||||
| +	.target	= jz4740_freq_target, |  | ||||||
| +	.get	= jz4740_freq_get, |  | ||||||
| +	.name	= "jz4740", |  | ||||||
| +}; |  | ||||||
| + |  | ||||||
| +static int __init jz4740_cpufreq_init(void) |  | ||||||
| +{ |  | ||||||
| +	return cpufreq_register_driver(&cpufreq_jz4740_driver); |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static void __exit jz4740_cpufreq_exit(void) |  | ||||||
| +{ |  | ||||||
| +	cpufreq_unregister_driver(&cpufreq_jz4740_driver); |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +module_init(jz4740_cpufreq_init); |  | ||||||
| +module_exit(jz4740_cpufreq_exit); |  | ||||||
| + |  | ||||||
| +MODULE_AUTHOR("Ulrich Hecht <ulrich.hecht@gmail.com>, " |  | ||||||
| +	      "Maarten ter Huurne <maarten@treewalker.org>"); |  | ||||||
| +MODULE_DESCRIPTION("cpufreq driver for Jz4740"); |  | ||||||
| +MODULE_LICENSE("GPL"); |  | ||||||
| --- a/arch/mips/kernel/cpufreq/Kconfig |  | ||||||
| +++ b/arch/mips/kernel/cpufreq/Kconfig |  | ||||||
| @@ -8,7 +8,7 @@ config MIPS_EXTERNAL_TIMER |  | ||||||
|  config MIPS_CPUFREQ |  | ||||||
|  	bool |  | ||||||
|  	default y |  | ||||||
| -	depends on CPU_SUPPORTS_CPUFREQ && MIPS_EXTERNAL_TIMER |  | ||||||
| +	depends on CPU_SUPPORTS_CPUFREQ |  | ||||||
|   |  | ||||||
|  if MIPS_CPUFREQ |  | ||||||
|   |  | ||||||
| @@ -24,6 +24,7 @@ config LOONGSON2_CPUFREQ |  | ||||||
|  	tristate "Loongson2 CPUFreq Driver" |  | ||||||
|  	select CPU_FREQ_TABLE |  | ||||||
|  	depends on MIPS_CPUFREQ |  | ||||||
| +	depends on MIPS_EXTERNAL_TIMER |  | ||||||
|  	help |  | ||||||
|  	  This option adds a CPUFreq driver for loongson processors which |  | ||||||
|  	  support software configurable cpu frequency. |  | ||||||
| @@ -34,6 +35,16 @@ config LOONGSON2_CPUFREQ |  | ||||||
|   |  | ||||||
|  	  If in doubt, say N. |  | ||||||
|   |  | ||||||
| +config CPU_FREQ_JZ |  | ||||||
| +	tristate "CPUfreq driver for JZ CPUs" |  | ||||||
| +	select CPU_FREQ_TABLE |  | ||||||
| +	depends on MACH_JZ4740 |  | ||||||
| +	default n |  | ||||||
| +	help |  | ||||||
| +	  This enables the CPUfreq driver for JZ CPUs. |  | ||||||
| + |  | ||||||
| +	  If in doubt, say N. |  | ||||||
| + |  | ||||||
|  endif	# CPU_FREQ |  | ||||||
|   |  | ||||||
|  endmenu |  | ||||||
| @@ -1,129 +0,0 @@ | |||||||
| From b95144c1b702f98c7902c75beb83f323701eb7c5 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Maarten ter Huurne <maarten@treewalker.org> |  | ||||||
| Date: Sun, 19 Jun 2011 10:57:18 +0200 |  | ||||||
| Subject: [PATCH 13/21] MMC: JZ4740: Added support for CPU frequency changing. |  | ||||||
|  |  | ||||||
| The MSC device clock is stopped before the frequency change. |  | ||||||
| After the change a new divider is computed and the clock is restarted. |  | ||||||
| Also the frequency change is postponed if an I/O operation is in progress. |  | ||||||
| --- |  | ||||||
|  drivers/mmc/host/jz4740_mmc.c |   69 +++++++++++++++++++++++++++++++++++++++- |  | ||||||
|  1 files changed, 67 insertions(+), 2 deletions(-) |  | ||||||
|  |  | ||||||
| --- a/drivers/mmc/host/jz4740_mmc.c |  | ||||||
| +++ b/drivers/mmc/host/jz4740_mmc.c |  | ||||||
| @@ -23,6 +23,7 @@ |  | ||||||
|  #include <linux/delay.h> |  | ||||||
|  #include <linux/scatterlist.h> |  | ||||||
|  #include <linux/clk.h> |  | ||||||
| +#include <linux/cpufreq.h> |  | ||||||
|   |  | ||||||
|  #include <linux/bitops.h> |  | ||||||
|  #include <linux/gpio.h> |  | ||||||
| @@ -685,6 +686,60 @@ static void jz4740_mmc_enable_sdio_irq(s |  | ||||||
|  	jz4740_mmc_set_irq_enabled(host, JZ_MMC_IRQ_SDIO, enable); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| +#ifdef CONFIG_CPU_FREQ |  | ||||||
| + |  | ||||||
| +static struct jz4740_mmc_host *cpufreq_host; |  | ||||||
| + |  | ||||||
| +static int jz4740_mmc_cpufreq_transition(struct notifier_block *nb, |  | ||||||
| +					 unsigned long val, void *data) |  | ||||||
| +{ |  | ||||||
| +	/* TODO: We only have to take action when the PLL freq changes: |  | ||||||
| +	         the main dividers have no influence on the MSC device clock. */ |  | ||||||
| + |  | ||||||
| +	if (val == CPUFREQ_PRECHANGE) { |  | ||||||
| +		mmc_claim_host(cpufreq_host->mmc); |  | ||||||
| +		clk_disable(cpufreq_host->clk); |  | ||||||
| +	} else if (val == CPUFREQ_POSTCHANGE) { |  | ||||||
| +		struct mmc_ios *ios = &cpufreq_host->mmc->ios; |  | ||||||
| +		if (ios->clock) |  | ||||||
| +			jz4740_mmc_set_clock_rate(cpufreq_host, ios->clock); |  | ||||||
| +		if (ios->power_mode != MMC_POWER_OFF) |  | ||||||
| +			clk_enable(cpufreq_host->clk); |  | ||||||
| +		mmc_release_host(cpufreq_host->mmc); |  | ||||||
| +	} |  | ||||||
| +	return 0; |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static struct notifier_block jz4740_mmc_cpufreq_nb = { |  | ||||||
| +	.notifier_call = jz4740_mmc_cpufreq_transition, |  | ||||||
| +}; |  | ||||||
| + |  | ||||||
| +static inline int jz4740_mmc_cpufreq_register(struct jz4740_mmc_host *host) |  | ||||||
| +{ |  | ||||||
| +	cpufreq_host = host; |  | ||||||
| +	return cpufreq_register_notifier(&jz4740_mmc_cpufreq_nb, |  | ||||||
| +					 CPUFREQ_TRANSITION_NOTIFIER); |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static inline void jz4740_mmc_cpufreq_unregister(void) |  | ||||||
| +{ |  | ||||||
| +	cpufreq_unregister_notifier(&jz4740_mmc_cpufreq_nb, |  | ||||||
| +				    CPUFREQ_TRANSITION_NOTIFIER); |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +#else |  | ||||||
| + |  | ||||||
| +static inline int jz4740_mmc_cpufreq_register(struct jz4740_mmc_host *host) |  | ||||||
| +{ |  | ||||||
| +	return 0; |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static inline void jz4740_mmc_cpufreq_unregister(void) |  | ||||||
| +{ |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +#endif |  | ||||||
| + |  | ||||||
|  static const struct mmc_host_ops jz4740_mmc_ops = { |  | ||||||
|  	.request	= jz4740_mmc_request, |  | ||||||
|  	.set_ios	= jz4740_mmc_set_ios, |  | ||||||
| @@ -834,11 +889,18 @@ static int __devinit jz4740_mmc_probe(st |  | ||||||
|  		goto err_free_host; |  | ||||||
|  	} |  | ||||||
|   |  | ||||||
| +	ret = jz4740_mmc_cpufreq_register(host); |  | ||||||
| +	if (ret) { |  | ||||||
| +		dev_err(&pdev->dev, |  | ||||||
| +			"Failed to register cpufreq transition notifier\n"); |  | ||||||
| +		goto err_clk_put; |  | ||||||
| +	} |  | ||||||
| + |  | ||||||
|  	host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |  | ||||||
|  	if (!host->mem) { |  | ||||||
|  		ret = -ENOENT; |  | ||||||
|  		dev_err(&pdev->dev, "Failed to get base platform memory\n"); |  | ||||||
| -		goto err_clk_put; |  | ||||||
| +		goto err_cpufreq_unreg; |  | ||||||
|  	} |  | ||||||
|   |  | ||||||
|  	host->mem = request_mem_region(host->mem->start, |  | ||||||
| @@ -846,7 +908,7 @@ static int __devinit jz4740_mmc_probe(st |  | ||||||
|  	if (!host->mem) { |  | ||||||
|  		ret = -EBUSY; |  | ||||||
|  		dev_err(&pdev->dev, "Failed to request base memory region\n"); |  | ||||||
| -		goto err_clk_put; |  | ||||||
| +		goto err_cpufreq_unreg; |  | ||||||
|  	} |  | ||||||
|   |  | ||||||
|  	host->base = ioremap_nocache(host->mem->start, resource_size(host->mem)); |  | ||||||
| @@ -929,6 +991,8 @@ err_iounmap: |  | ||||||
|  	iounmap(host->base); |  | ||||||
|  err_release_mem_region: |  | ||||||
|  	release_mem_region(host->mem->start, resource_size(host->mem)); |  | ||||||
| +err_cpufreq_unreg: |  | ||||||
| +	jz4740_mmc_cpufreq_unregister(); |  | ||||||
|  err_clk_put: |  | ||||||
|  	clk_put(host->clk); |  | ||||||
|  err_free_host: |  | ||||||
| @@ -958,6 +1022,7 @@ static int __devexit jz4740_mmc_remove(s |  | ||||||
|  	iounmap(host->base); |  | ||||||
|  	release_mem_region(host->mem->start, resource_size(host->mem)); |  | ||||||
|   |  | ||||||
| +	jz4740_mmc_cpufreq_unregister(); |  | ||||||
|  	clk_put(host->clk); |  | ||||||
|   |  | ||||||
|  	platform_set_drvdata(pdev, NULL); |  | ||||||
| @@ -1,91 +0,0 @@ | |||||||
| From 2dcb0ca66d0bffc23d5f001fad81fb1a7a2c371b Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Maarten ter Huurne <maarten@treewalker.org> |  | ||||||
| Date: Tue, 28 Jun 2011 22:28:59 +0200 |  | ||||||
| Subject: [PATCH 14/21] MIPS: JZ4740: reset: Initialize hibernate wakeup |  | ||||||
|  counters. |  | ||||||
|  |  | ||||||
| In hibernation mode only the wakeup logic and the RTC are left running, |  | ||||||
| so this is what users perceive as power down. |  | ||||||
|  |  | ||||||
| If the counters are not initialized, the corresponding pin (typically |  | ||||||
| connected to the power button) has to be asserted for two seconds |  | ||||||
| before the device wakes up. Most users expect a shorter wakeup time. |  | ||||||
|  |  | ||||||
| I took the timing values of 100 ms and 60 ms from BouKiCHi's patch for |  | ||||||
| the Dingoo A320 kernel. |  | ||||||
| --- |  | ||||||
|  arch/mips/jz4740/reset.c |   46 ++++++++++++++++++++++++++++++++++++++++------ |  | ||||||
|  1 files changed, 40 insertions(+), 6 deletions(-) |  | ||||||
|  |  | ||||||
| --- a/arch/mips/jz4740/reset.c |  | ||||||
| +++ b/arch/mips/jz4740/reset.c |  | ||||||
| @@ -21,6 +21,9 @@ |  | ||||||
|  #include <asm/mach-jz4740/base.h> |  | ||||||
|  #include <asm/mach-jz4740/timer.h> |  | ||||||
|   |  | ||||||
| +#include "reset.h" |  | ||||||
| +#include "clock.h" |  | ||||||
| + |  | ||||||
|  static void jz4740_halt(void) |  | ||||||
|  { |  | ||||||
|  	while (1) { |  | ||||||
| @@ -53,21 +56,52 @@ static void jz4740_restart(char *command |  | ||||||
|  	jz4740_halt(); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| -#define JZ_REG_RTC_CTRL		0x00 |  | ||||||
| -#define JZ_REG_RTC_HIBERNATE	0x20 |  | ||||||
| - |  | ||||||
| -#define JZ_RTC_CTRL_WRDY	BIT(7) |  | ||||||
| +#define JZ_REG_RTC_CTRL			0x00 |  | ||||||
| +#define JZ_REG_RTC_HIBERNATE		0x20 |  | ||||||
| +#define JZ_REG_RTC_WAKEUP_FILTER	0x24 |  | ||||||
| +#define JZ_REG_RTC_RESET_COUNTER	0x28 |  | ||||||
| + |  | ||||||
| +#define JZ_RTC_CTRL_WRDY		BIT(7) |  | ||||||
| +#define JZ_RTC_WAKEUP_FILTER_MASK	0x0000FFE0 |  | ||||||
| +#define JZ_RTC_RESET_COUNTER_MASK	0x00000FE0 |  | ||||||
|   |  | ||||||
| -static void jz4740_power_off(void) |  | ||||||
| +static inline void jz4740_rtc_wait_ready(void __iomem *rtc_base) |  | ||||||
|  { |  | ||||||
| -	void __iomem *rtc_base = ioremap(JZ4740_RTC_BASE_ADDR, 0x24); |  | ||||||
|  	uint32_t ctrl; |  | ||||||
| - |  | ||||||
|  	do { |  | ||||||
|  		ctrl = readl(rtc_base + JZ_REG_RTC_CTRL); |  | ||||||
|  	} while (!(ctrl & JZ_RTC_CTRL_WRDY)); |  | ||||||
| +} |  | ||||||
|   |  | ||||||
| +static void jz4740_power_off(void) |  | ||||||
| +{ |  | ||||||
| +	void __iomem *rtc_base = ioremap(JZ4740_RTC_BASE_ADDR, 0x38); |  | ||||||
| +	unsigned long long wakeup_filter_ticks; |  | ||||||
| +	unsigned long long reset_counter_ticks; |  | ||||||
| + |  | ||||||
| +	/* Set minimum wakeup pin assertion time: 100 ms. |  | ||||||
| +	   Range is 0 to 2 sec if RTC is clocked at 32 kHz. */ |  | ||||||
| +	wakeup_filter_ticks = (100 * jz4740_clock_bdata.rtc_rate) / 1000; |  | ||||||
| +	if (wakeup_filter_ticks < JZ_RTC_WAKEUP_FILTER_MASK) |  | ||||||
| +		wakeup_filter_ticks &= JZ_RTC_WAKEUP_FILTER_MASK; |  | ||||||
| +	else |  | ||||||
| +		wakeup_filter_ticks = JZ_RTC_WAKEUP_FILTER_MASK; |  | ||||||
| +	jz4740_rtc_wait_ready(rtc_base); |  | ||||||
| +	writel(wakeup_filter_ticks, rtc_base + JZ_REG_RTC_WAKEUP_FILTER); |  | ||||||
| + |  | ||||||
| +	/* Set reset pin low-level assertion time after wakeup: 60 ms. |  | ||||||
| +	   Range is 0 to 125 ms if RTC is clocked at 32 kHz. */ |  | ||||||
| +	reset_counter_ticks = (60 * jz4740_clock_bdata.rtc_rate) / 1000; |  | ||||||
| +	if (reset_counter_ticks < JZ_RTC_RESET_COUNTER_MASK) |  | ||||||
| +		reset_counter_ticks &= JZ_RTC_RESET_COUNTER_MASK; |  | ||||||
| +	else |  | ||||||
| +		reset_counter_ticks = JZ_RTC_RESET_COUNTER_MASK; |  | ||||||
| +	jz4740_rtc_wait_ready(rtc_base); |  | ||||||
| +	writel(reset_counter_ticks, rtc_base + JZ_REG_RTC_RESET_COUNTER); |  | ||||||
| + |  | ||||||
| +	jz4740_rtc_wait_ready(rtc_base); |  | ||||||
|  	writel(1, rtc_base + JZ_REG_RTC_HIBERNATE); |  | ||||||
| + |  | ||||||
|  	jz4740_halt(); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| @@ -1,31 +0,0 @@ | |||||||
| From 515f8006c03e1065bf98c9148a9ea787e2d120d3 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Maarten ter Huurne <maarten@treewalker.org> |  | ||||||
| Date: Wed, 10 Aug 2011 00:20:16 +0200 |  | ||||||
| Subject: [PATCH 15/21] ASoC: JZ4740: Replaced comma operators with |  | ||||||
|  semicolons. |  | ||||||
|  |  | ||||||
| They were harmless but also unnecessary, probably a leftover from earlier code. |  | ||||||
| --- |  | ||||||
|  sound/soc/jz4740/jz4740-i2s.c |    4 ++-- |  | ||||||
|  1 files changed, 2 insertions(+), 2 deletions(-) |  | ||||||
|  |  | ||||||
| --- a/sound/soc/jz4740/jz4740-i2s.c |  | ||||||
| +++ b/sound/soc/jz4740/jz4740-i2s.c |  | ||||||
| @@ -346,7 +346,7 @@ static void jz4740_i2c_init_pcm_config(s |  | ||||||
|   |  | ||||||
|  	/* Playback */ |  | ||||||
|  	dma_config = &i2s->pcm_config_playback.dma_config; |  | ||||||
| -	dma_config->src_width = JZ4740_DMA_WIDTH_32BIT, |  | ||||||
| +	dma_config->src_width = JZ4740_DMA_WIDTH_32BIT; |  | ||||||
|  	dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE; |  | ||||||
|  	dma_config->request_type = JZ4740_DMA_TYPE_AIC_TRANSMIT; |  | ||||||
|  	dma_config->flags = JZ4740_DMA_SRC_AUTOINC; |  | ||||||
| @@ -355,7 +355,7 @@ static void jz4740_i2c_init_pcm_config(s |  | ||||||
|   |  | ||||||
|  	/* Capture */ |  | ||||||
|  	dma_config = &i2s->pcm_config_capture.dma_config; |  | ||||||
| -	dma_config->dst_width = JZ4740_DMA_WIDTH_32BIT, |  | ||||||
| +	dma_config->dst_width = JZ4740_DMA_WIDTH_32BIT; |  | ||||||
|  	dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE; |  | ||||||
|  	dma_config->request_type = JZ4740_DMA_TYPE_AIC_RECEIVE; |  | ||||||
|  	dma_config->flags = JZ4740_DMA_DST_AUTOINC; |  | ||||||
| @@ -1,89 +0,0 @@ | |||||||
| From 8a5087fe59e31efb8641e704058328997c3c8ff1 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Maarten ter Huurne <maarten@treewalker.org> |  | ||||||
| Date: Wed, 10 Aug 2011 00:25:11 +0200 |  | ||||||
| Subject: [PATCH 16/21] ASoC: JZ4740: Support buffer size that is not a |  | ||||||
|  multiple of period size. |  | ||||||
|  |  | ||||||
| This fixes glitches triggered by libao, which sets time-based intervals |  | ||||||
| instead of byte-based intervals like SDL does. |  | ||||||
|  |  | ||||||
| Thanks to Paul Cercueil for figuring out that the buffer size was causing |  | ||||||
| the glitches and to Lars Clausen for helping me write the fix. |  | ||||||
| --- |  | ||||||
|  sound/soc/jz4740/jz4740-pcm.c |   21 ++++++++++++++++++--- |  | ||||||
|  1 files changed, 18 insertions(+), 3 deletions(-) |  | ||||||
|  |  | ||||||
| --- a/sound/soc/jz4740/jz4740-pcm.c |  | ||||||
| +++ b/sound/soc/jz4740/jz4740-pcm.c |  | ||||||
| @@ -31,6 +31,7 @@ |  | ||||||
|   |  | ||||||
|  struct jz4740_runtime_data { |  | ||||||
|  	unsigned long dma_period; |  | ||||||
| +	unsigned long dma_period_left; |  | ||||||
|  	dma_addr_t dma_start; |  | ||||||
|  	dma_addr_t dma_pos; |  | ||||||
|  	dma_addr_t dma_end; |  | ||||||
| @@ -67,10 +68,13 @@ static void jz4740_pcm_start_transfer(st |  | ||||||
|  	if (prtd->dma_pos == prtd->dma_end) |  | ||||||
|  		prtd->dma_pos = prtd->dma_start; |  | ||||||
|   |  | ||||||
| -	if (prtd->dma_pos + prtd->dma_period > prtd->dma_end) |  | ||||||
| +	if (prtd->dma_period_left == 0) |  | ||||||
| +		prtd->dma_period_left = prtd->dma_period; |  | ||||||
| + |  | ||||||
| +	if (prtd->dma_pos + prtd->dma_period_left > prtd->dma_end) |  | ||||||
|  		count = prtd->dma_end - prtd->dma_pos; |  | ||||||
|  	else |  | ||||||
| -		count = prtd->dma_period; |  | ||||||
| +		count = prtd->dma_period_left; |  | ||||||
|   |  | ||||||
|  	jz4740_dma_disable(prtd->dma); |  | ||||||
|   |  | ||||||
| @@ -85,6 +89,7 @@ static void jz4740_pcm_start_transfer(st |  | ||||||
|  	jz4740_dma_set_transfer_count(prtd->dma, count); |  | ||||||
|   |  | ||||||
|  	prtd->dma_pos += count; |  | ||||||
| +	prtd->dma_period_left -= count; |  | ||||||
|   |  | ||||||
|  	jz4740_dma_enable(prtd->dma); |  | ||||||
|  } |  | ||||||
| @@ -96,7 +101,8 @@ static void jz4740_pcm_dma_transfer_done |  | ||||||
|  	struct snd_pcm_runtime *runtime = substream->runtime; |  | ||||||
|  	struct jz4740_runtime_data *prtd = runtime->private_data; |  | ||||||
|   |  | ||||||
| -	snd_pcm_period_elapsed(substream); |  | ||||||
| +	if (prtd->dma_period_left == 0) |  | ||||||
| +		snd_pcm_period_elapsed(substream); |  | ||||||
|   |  | ||||||
|  	jz4740_pcm_start_transfer(prtd, substream); |  | ||||||
|  } |  | ||||||
| @@ -133,6 +139,7 @@ static int jz4740_pcm_hw_params(struct s |  | ||||||
|  	runtime->dma_bytes = params_buffer_bytes(params); |  | ||||||
|   |  | ||||||
|  	prtd->dma_period = params_period_bytes(params); |  | ||||||
| +	prtd->dma_period_left = 0; |  | ||||||
|  	prtd->dma_start = runtime->dma_addr; |  | ||||||
|  	prtd->dma_pos = prtd->dma_start; |  | ||||||
|  	prtd->dma_end = prtd->dma_start + runtime->dma_bytes; |  | ||||||
| @@ -160,6 +167,7 @@ static int jz4740_pcm_prepare(struct snd |  | ||||||
|  	if (!prtd->dma) |  | ||||||
|  		return -EBUSY; |  | ||||||
|   |  | ||||||
| +	prtd->dma_period_left = 0; |  | ||||||
|  	prtd->dma_pos = prtd->dma_start; |  | ||||||
|   |  | ||||||
|  	return 0; |  | ||||||
| @@ -219,6 +227,13 @@ static int jz4740_pcm_open(struct snd_pc |  | ||||||
|  	if (prtd == NULL) |  | ||||||
|  		return -ENOMEM; |  | ||||||
|   |  | ||||||
| +	/* Force period and buffer size to be a multiple of the DMA transfer |  | ||||||
| +	 * size, which is 16 bytes. */ |  | ||||||
| +	snd_pcm_hw_constraint_step(runtime, 0, |  | ||||||
| +				   SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 16); |  | ||||||
| +	snd_pcm_hw_constraint_step(runtime, 0, |  | ||||||
| +				   SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 16); |  | ||||||
| + |  | ||||||
|  	snd_soc_set_runtime_hwparams(substream, &jz4740_pcm_hardware); |  | ||||||
|   |  | ||||||
|  	runtime->private_data = prtd; |  | ||||||
| @@ -1,21 +0,0 @@ | |||||||
| From cdb15b56aa9517a8cdbd14724088227514622a1b Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Maarten ter Huurne <maarten@treewalker.org> |  | ||||||
| Date: Wed, 11 Jan 2012 22:36:03 +0100 |  | ||||||
| Subject: [PATCH 17/21] MIPS: JZ4740: qi_lb60: Look for NAND chip in bank 1. |  | ||||||
|  |  | ||||||
| All NanoNotes have their NAND in bank 1. |  | ||||||
| Specifying the bank is required since commit e7ca5a665877a030. |  | ||||||
| --- |  | ||||||
|  arch/mips/jz4740/board-qi_lb60.c |    1 + |  | ||||||
|  1 files changed, 1 insertions(+), 0 deletions(-) |  | ||||||
|  |  | ||||||
| --- a/arch/mips/jz4740/board-qi_lb60.c |  | ||||||
| +++ b/arch/mips/jz4740/board-qi_lb60.c |  | ||||||
| @@ -140,6 +140,7 @@ static void qi_lb60_nand_ident(struct pl |  | ||||||
|  static struct jz_nand_platform_data qi_lb60_nand_pdata = { |  | ||||||
|  	.ident_callback = qi_lb60_nand_ident, |  | ||||||
|  	.busy_gpio = 94, |  | ||||||
| +	.banks = { 1 }, |  | ||||||
|  }; |  | ||||||
|   |  | ||||||
|  /* Keyboard*/ |  | ||||||
| @@ -1,121 +0,0 @@ | |||||||
| From 94f2b91d2a42854a8869d54a758bc88757d7f6d9 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Axel Lin <axel.lin@gmail.com> |  | ||||||
| Date: Fri, 6 Jan 2012 11:30:10 +0800 |  | ||||||
| Subject: [PATCH 18/21] ASoC: jz4740: Convert qi_lb60 to use |  | ||||||
|  snd_soc_register_card() |  | ||||||
|  |  | ||||||
| Use snd_soc_register_card() instead of creating a "soc-audio" platform device. |  | ||||||
|  |  | ||||||
| Signed-off-by: Axel Lin <axel.lin@gmail.com> |  | ||||||
| --- |  | ||||||
|  arch/mips/jz4740/board-qi_lb60.c |    6 ++++ |  | ||||||
|  sound/soc/jz4740/qi_lb60.c       |   56 +++++++++++++++++-------------------- |  | ||||||
|  2 files changed, 32 insertions(+), 30 deletions(-) |  | ||||||
|  |  | ||||||
| --- a/arch/mips/jz4740/board-qi_lb60.c |  | ||||||
| +++ b/arch/mips/jz4740/board-qi_lb60.c |  | ||||||
| @@ -418,6 +418,11 @@ static struct platform_device qi_lb60_ch |  | ||||||
|  	}, |  | ||||||
|  }; |  | ||||||
|   |  | ||||||
| +/* audio */ |  | ||||||
| +static struct platform_device qi_lb60_audio_device = { |  | ||||||
| +	.name = "qi-lb60-audio", |  | ||||||
| +	.id = -1, |  | ||||||
| +}; |  | ||||||
|   |  | ||||||
|  static struct platform_device *jz_platform_devices[] __initdata = { |  | ||||||
|  	&jz4740_udc_device, |  | ||||||
| @@ -434,6 +439,7 @@ static struct platform_device *jz_platfo |  | ||||||
|  	&qi_lb60_gpio_keys, |  | ||||||
|  	&qi_lb60_pwm_beeper, |  | ||||||
|  	&qi_lb60_charger_device, |  | ||||||
| +	&qi_lb60_audio_device, |  | ||||||
|  }; |  | ||||||
|   |  | ||||||
|  static void __init board_gpio_setup(void) |  | ||||||
| --- a/sound/soc/jz4740/qi_lb60.c |  | ||||||
| +++ b/sound/soc/jz4740/qi_lb60.c |  | ||||||
| @@ -91,56 +91,52 @@ static struct snd_soc_card qi_lb60 = { |  | ||||||
|  	.num_dapm_routes = ARRAY_SIZE(qi_lb60_routes), |  | ||||||
|  }; |  | ||||||
|   |  | ||||||
| -static struct platform_device *qi_lb60_snd_device; |  | ||||||
| - |  | ||||||
|  static const struct gpio qi_lb60_gpios[] = { |  | ||||||
|  	{ QI_LB60_SND_GPIO, GPIOF_OUT_INIT_LOW, "SND" }, |  | ||||||
|  	{ QI_LB60_AMP_GPIO, GPIOF_OUT_INIT_LOW, "AMP" }, |  | ||||||
|  }; |  | ||||||
|   |  | ||||||
| -static int __init qi_lb60_init(void) |  | ||||||
| +static int __devinit qi_lb60_probe(struct platform_device *pdev) |  | ||||||
|  { |  | ||||||
| +	struct snd_soc_card *card = &qi_lb60; |  | ||||||
|  	int ret; |  | ||||||
|   |  | ||||||
| -	qi_lb60_snd_device = platform_device_alloc("soc-audio", -1); |  | ||||||
| - |  | ||||||
| -	if (!qi_lb60_snd_device) |  | ||||||
| -		return -ENOMEM; |  | ||||||
| - |  | ||||||
|  	ret = gpio_request_array(qi_lb60_gpios, ARRAY_SIZE(qi_lb60_gpios)); |  | ||||||
| -	if (ret) { |  | ||||||
| -		pr_err("qi_lb60 snd: Failed to request gpios: %d\n", ret); |  | ||||||
| -		goto err_device_put; |  | ||||||
| -	} |  | ||||||
| +	if (ret) |  | ||||||
| +		return ret; |  | ||||||
|   |  | ||||||
| -	platform_set_drvdata(qi_lb60_snd_device, &qi_lb60); |  | ||||||
| +	card->dev = &pdev->dev; |  | ||||||
|   |  | ||||||
| -	ret = platform_device_add(qi_lb60_snd_device); |  | ||||||
| +	ret = snd_soc_register_card(card); |  | ||||||
|  	if (ret) { |  | ||||||
| -		pr_err("qi_lb60 snd: Failed to add snd soc device: %d\n", ret); |  | ||||||
| -		goto err_unset_pdata; |  | ||||||
| +		dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", |  | ||||||
| +			ret); |  | ||||||
| +		gpio_free_array(qi_lb60_gpios, ARRAY_SIZE(qi_lb60_gpios)); |  | ||||||
|  	} |  | ||||||
| - |  | ||||||
| -	 return 0; |  | ||||||
| - |  | ||||||
| -err_unset_pdata: |  | ||||||
| -	platform_set_drvdata(qi_lb60_snd_device, NULL); |  | ||||||
| -/*err_gpio_free_array:*/ |  | ||||||
| -	gpio_free_array(qi_lb60_gpios, ARRAY_SIZE(qi_lb60_gpios)); |  | ||||||
| -err_device_put: |  | ||||||
| -	platform_device_put(qi_lb60_snd_device); |  | ||||||
| - |  | ||||||
|  	return ret; |  | ||||||
|  } |  | ||||||
| -module_init(qi_lb60_init); |  | ||||||
|   |  | ||||||
| -static void __exit qi_lb60_exit(void) |  | ||||||
| +static int __devexit qi_lb60_remove(struct platform_device *pdev) |  | ||||||
|  { |  | ||||||
| -	platform_device_unregister(qi_lb60_snd_device); |  | ||||||
| +	struct snd_soc_card *card = platform_get_drvdata(pdev); |  | ||||||
| + |  | ||||||
| +	snd_soc_unregister_card(card); |  | ||||||
|  	gpio_free_array(qi_lb60_gpios, ARRAY_SIZE(qi_lb60_gpios)); |  | ||||||
| +	return 0; |  | ||||||
|  } |  | ||||||
| -module_exit(qi_lb60_exit); |  | ||||||
| + |  | ||||||
| +static struct platform_driver qi_lb60_driver = { |  | ||||||
| +	.driver		= { |  | ||||||
| +		.name	= "qi-lb60-audio", |  | ||||||
| +		.owner	= THIS_MODULE, |  | ||||||
| +	}, |  | ||||||
| +	.probe		= qi_lb60_probe, |  | ||||||
| +	.remove		= __devexit_p(qi_lb60_remove), |  | ||||||
| +}; |  | ||||||
| + |  | ||||||
| +module_platform_driver(qi_lb60_driver); |  | ||||||
|   |  | ||||||
|  MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); |  | ||||||
|  MODULE_DESCRIPTION("ALSA SoC QI LB60 Audio support"); |  | ||||||
|  MODULE_LICENSE("GPL v2"); |  | ||||||
| +MODULE_ALIAS("platform:qi-lb60-audio"); |  | ||||||
| @@ -1,38 +0,0 @@ | |||||||
| From 159c4d81899db05a57bc4a0d55083e484c3d8a43 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Lars-Peter Clausen <lars@metafoo.de> |  | ||||||
| Date: Sat, 24 Apr 2010 12:23:28 +0200 |  | ||||||
| Subject: [PATCH 19/21] Framebuffer notifier: Call notifier callbacks prior to |  | ||||||
|  blanking the screen |  | ||||||
|  |  | ||||||
| --- |  | ||||||
|  drivers/video/fbmem.c |    8 ++++++-- |  | ||||||
|  1 files changed, 6 insertions(+), 2 deletions(-) |  | ||||||
|  |  | ||||||
| --- a/drivers/video/fbmem.c |  | ||||||
| +++ b/drivers/video/fbmem.c |  | ||||||
| @@ -1046,12 +1046,12 @@ fb_set_var(struct fb_info *info, struct |  | ||||||
|  int |  | ||||||
|  fb_blank(struct fb_info *info, int blank) |  | ||||||
|  {	 |  | ||||||
| - 	int ret = -EINVAL; |  | ||||||
| + 	int ret = 0; |  | ||||||
|   |  | ||||||
|   	if (blank > FB_BLANK_POWERDOWN) |  | ||||||
|   		blank = FB_BLANK_POWERDOWN; |  | ||||||
|   |  | ||||||
| -	if (info->fbops->fb_blank) |  | ||||||
| +	if (info->fbops->fb_blank && blank == FB_BLANK_UNBLANK) |  | ||||||
|   		ret = info->fbops->fb_blank(blank, info); |  | ||||||
|   |  | ||||||
|   	if (!ret) { |  | ||||||
| @@ -1062,6 +1062,10 @@ fb_blank(struct fb_info *info, int blank |  | ||||||
|  		fb_notifier_call_chain(FB_EVENT_BLANK, &event); |  | ||||||
|  	} |  | ||||||
|   |  | ||||||
| +	if (info->fbops->fb_blank && blank != FB_BLANK_UNBLANK) |  | ||||||
| + 		ret = info->fbops->fb_blank(blank, info); |  | ||||||
| + |  | ||||||
| + |  | ||||||
|   	return ret; |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| @@ -1,26 +0,0 @@ | |||||||
| From 1d7ef3445db5aebf48c90b20e18630633623c750 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Xiangfu Liu <xiangfu@macbook.(none)> |  | ||||||
| Date: Fri, 19 Aug 2011 15:46:52 +0800 |  | ||||||
| Subject: [PATCH 20/21] qi_lb60: NAND: add data partition |  | ||||||
|  |  | ||||||
| --- |  | ||||||
|  arch/mips/jz4740/board-qi_lb60.c |    7 ++++++- |  | ||||||
|  1 files changed, 6 insertions(+), 1 deletions(-) |  | ||||||
|  |  | ||||||
| --- a/arch/mips/jz4740/board-qi_lb60.c |  | ||||||
| +++ b/arch/mips/jz4740/board-qi_lb60.c |  | ||||||
| @@ -118,8 +118,13 @@ static struct mtd_partition qi_lb60_part |  | ||||||
|  	{ |  | ||||||
|  		.name = "NAND ROOTFS partition", |  | ||||||
|  		.offset = 8 * 0x100000, |  | ||||||
| -		.size = (504 + 512 + 1024) * 0x100000, |  | ||||||
| +		.size = 512 * 0x100000, |  | ||||||
|  	}, |  | ||||||
| +        {  |  | ||||||
| +		.name = "NAND DATA partition", |  | ||||||
| +          	.offset = 520 * 0x100000, |  | ||||||
| +          	.size = 1528 * 0x100000, |  | ||||||
| +        }, |  | ||||||
|  }; |  | ||||||
|   |  | ||||||
|  static void qi_lb60_nand_ident(struct platform_device *pdev, |  | ||||||
| @@ -1,20 +0,0 @@ | |||||||
| From a37ca6eb8cb52d620feff3323a3be4da24f5bee8 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Xiangfu <xiangfu@openmobilefree.net> |  | ||||||
| Date: Fri, 16 Mar 2012 17:48:45 +0800 |  | ||||||
| Subject: [PATCH 21/21] rtc: jz4740 fix hwclock give time out |  | ||||||
|  |  | ||||||
| --- |  | ||||||
|  drivers/rtc/rtc-jz4740.c |    2 ++ |  | ||||||
|  1 files changed, 2 insertions(+), 0 deletions(-) |  | ||||||
|  |  | ||||||
| --- a/drivers/rtc/rtc-jz4740.c |  | ||||||
| +++ b/drivers/rtc/rtc-jz4740.c |  | ||||||
| @@ -280,6 +280,8 @@ static int __devinit jz4740_rtc_probe(st |  | ||||||
|  		} |  | ||||||
|  	} |  | ||||||
|   |  | ||||||
| +	jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_1HZ_IRQ, 1); |  | ||||||
| + |  | ||||||
|  	return 0; |  | ||||||
|   |  | ||||||
|  err_free_irq: |  | ||||||
| @@ -1,33 +0,0 @@ | |||||||
| # CONFIG_BACKLIGHT_CLASS_DEVICE is not set |  | ||||||
| CONFIG_BACKLIGHT_LCD_SUPPORT=y |  | ||||||
| CONFIG_INPUT_PWM_BEEPER=y |  | ||||||
| CONFIG_KEYBOARD_GPIO=y |  | ||||||
| CONFIG_KEYBOARD_MATRIX=y |  | ||||||
| CONFIG_LCD_CLASS_DEVICE=y |  | ||||||
| CONFIG_LCD_ILI8960=y |  | ||||||
| # CONFIG_LCD_L4F00242T03 is not set |  | ||||||
| # CONFIG_LCD_LMS283GF05 is not set |  | ||||||
| # CONFIG_LCD_LTV350QV is not set |  | ||||||
| # CONFIG_LCD_PLATFORM is not set |  | ||||||
| # CONFIG_LCD_TDO24M is not set |  | ||||||
| # CONFIG_LCD_VGG2432A4 is not set |  | ||||||
| CONFIG_LOGO=y |  | ||||||
| # CONFIG_LOGO_LINUX_CLUT224 is not set |  | ||||||
| # CONFIG_LOGO_LINUX_MONO is not set |  | ||||||
| # CONFIG_LOGO_LINUX_VGA16 is not set |  | ||||||
| CONFIG_REGMAP_SPI=y |  | ||||||
| CONFIG_SND_HWDEP=y |  | ||||||
| CONFIG_SND_MIXER_OSS=y |  | ||||||
| CONFIG_SND_PCM_OSS=y |  | ||||||
| CONFIG_SND_SEQUENCER=y |  | ||||||
| # CONFIG_SND_SEQUENCER_OSS is not set |  | ||||||
| CONFIG_SND_SEQ_DUMMY=y |  | ||||||
| # CONFIG_SND_VIRMIDI is not set |  | ||||||
| CONFIG_SOUND_OSS_CORE=y |  | ||||||
| CONFIG_SOUND_OSS_CORE_PRECLAIM=y |  | ||||||
| CONFIG_SPI=y |  | ||||||
| CONFIG_SPI_BITBANG=y |  | ||||||
| CONFIG_SPI_GPIO=y |  | ||||||
| CONFIG_SPI_MASTER=y |  | ||||||
| # CONFIG_USB_FUSB300 is not set |  | ||||||
| CONFIG_USB_JZ4740=y |  | ||||||
		Reference in New Issue
	
	Block a user
	 Gabor Juhos
					Gabor Juhos