Skip to content

Commit

Permalink
Add cpufreq driver
Browse files Browse the repository at this point in the history
  • Loading branch information
popcornmix committed Sep 9, 2012
1 parent 55549f3 commit adae199
Show file tree
Hide file tree
Showing 8 changed files with 380 additions and 37 deletions.
1 change: 1 addition & 0 deletions arch/arm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -963,6 +963,7 @@ config ARCH_BCM2708
select HAVE_SCHED_CLOCK
select NEED_MACH_MEMORY_H
select CLKDEV_LOOKUP
select ARCH_HAS_CPUFREQ
select GENERIC_CLOCKEVENTS
select ARM_ERRATA_411920
select MACH_BCM2708
Expand Down
6 changes: 6 additions & 0 deletions arch/arm/configs/bcmrpi_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
CONFIG_CMDLINE="dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext3 rootwait"
CONFIG_KEXEC=y
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_STAT=m
CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
CONFIG_CPU_IDLE=y
CONFIG_VFP=y
CONFIG_BINFMT_MISC=m
Expand Down
81 changes: 73 additions & 8 deletions arch/arm/mach-bcm2708/include/mach/vcio.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,82 @@
#define BCM_VCIO_DRIVER_NAME "bcm2708_vcio"

/* Constants shared with the ARM identifying separate mailbox channels */
#define MBOX_CHAN_POWER 0 /* for use by the power management interface */
#define MBOX_CHAN_FB 1 /* for use by the frame buffer */
#define MBOX_CHAN_VUART 2 /* for use by the virtual UART */
#define MBOX_CHAN_VCHIQ 3 /* for use by the VCHIQ interface */
#define MBOX_CHAN_LEDS 4 /* for use by the leds interface */
#define MBOX_CHAN_BUTTONS 5 /* for use by the buttons interface */
#define MBOX_CHAN_TOUCH 6 /* for use by the touchscreen interface */
#define MBOX_CHAN_POWER 0 /* for use by the power management interface */
#define MBOX_CHAN_FB 1 /* for use by the frame buffer */
#define MBOX_CHAN_VCHIQ 3 /* for use by the VCHIQ interface */
#define MBOX_CHAN_PROPERTY 8 /* for use by the property channel */
#define MBOX_CHAN_COUNT 9
#define MBOX_CHAN_COUNT 9

/* Mailbox property tags */
enum {
VCMSG_PROPERTY_END = 0x00000000,
VCMSG_GET_FIRMWARE_REVISION = 0x00000001,
VCMSG_GET_BOARD_MODEL = 0x00010001,
VCMSG_GET_BOARD_REVISION = 0x00020002,
VCMSG_GET_BOARD_MAC_ADDRESS = 0x00020003,
VCMSG_GET_BOARD_SERIAL = 0x00020004,
VCMSG_GET_ARM_MEMORY = 0x00020005,
VCMSG_GET_VC_MEMORY = 0x00020006,
VCMSG_GET_CLOCKS = 0x00020007,
VCMSG_GET_COMMAND_LINE = 0x00050001,
VCMSG_GET_DMA_CHANNELS = 0x00060001,
VCMSG_GET_POWER_STATE = 0x00020001,
VCMSG_GET_TIMING = 0x00020002,
VCMSG_SET_POWER_STATE = 0x00028001,
VCMSG_GET_CLOCK_STATE = 0x00030001,
VCMSG_SET_CLOCK_STATE = 0x00038001,
VCMSG_GET_CLOCK_RATE = 0x00030002,
VCMSG_SET_CLOCK_RATE = 0x00038002,
VCMSG_GET_VOLTAGE = 0x00030003,
VCMSG_SET_VOLTAGE = 0x00038003,
VCMSG_GET_MAX_CLOCK = 0x00030004,
VCMSG_GET_MAX_VOLTAGE = 0x00030005,
VCMSG_GET_TEMPERATURE = 0x00030006,
VCMSG_GET_MIN_CLOCK = 0x00030007,
VCMSG_GET_MIN_VOLTAGE = 0x00030008,
VCMSG_GET_TURBO = 0x00030009,
VCMSG_SET_TURBO = 0x00038009,
VCMSG_SET_ALLOCATE_BUFFER = 0x00040001,
VCMSG_SET_RELEASE_BUFFER = 0x00048001,
VCMSG_SET_BLANK_SCREEN = 0x00040002,
VCMSG_TST_BLANK_SCREEN = 0x00044002,
VCMSG_GET_PHYSICAL_WIDTH_HEIGHT = 0x00040003,
VCMSG_TST_PHYSICAL_WIDTH_HEIGHT = 0x00044003,
VCMSG_SET_PHYSICAL_WIDTH_HEIGHT = 0x00048003,
VCMSG_GET_VIRTUAL_WIDTH_HEIGHT = 0x00040004,
VCMSG_TST_VIRTUAL_WIDTH_HEIGHT = 0x00044004,
VCMSG_SET_VIRTUAL_WIDTH_HEIGHT = 0x00048004,
VCMSG_GET_DEPTH = 0x00040005,
VCMSG_TST_DEPTH = 0x00044005,
VCMSG_SET_DEPTH = 0x00048005,
VCMSG_GET_PIXEL_ORDER = 0x00040006,
VCMSG_TST_PIXEL_ORDER = 0x00044006,
VCMSG_SET_PIXEL_ORDER = 0x00048006,
VCMSG_GET_ALPHA_MODE = 0x00040007,
VCMSG_TST_ALPHA_MODE = 0x00044007,
VCMSG_SET_ALPHA_MODE = 0x00048007,
VCMSG_GET_PITCH = 0x00040008,
VCMSG_TST_PITCH = 0x00044008,
VCMSG_SET_PITCH = 0x00048008,
VCMSG_GET_VIRTUAL_OFFSET = 0x00040009,
VCMSG_TST_VIRTUAL_OFFSET = 0x00044009,
VCMSG_SET_VIRTUAL_OFFSET = 0x00048009,
VCMSG_GET_OVERSCAN = 0x0004000a,
VCMSG_TST_OVERSCAN = 0x0004400a,
VCMSG_SET_OVERSCAN = 0x0004800a,
VCMSG_GET_PALETTE = 0x0004000b,
VCMSG_TST_PALETTE = 0x0004400b,
VCMSG_SET_PALETTE = 0x0004800b,
VCMSG_GET_LAYER = 0x0004000c,
VCMSG_TST_LAYER = 0x0004400c,
VCMSG_SET_LAYER = 0x0004800c,
VCMSG_GET_TRANSFORM = 0x0004000d,
VCMSG_TST_TRANSFORM = 0x0004400d,
VCMSG_SET_TRANSFORM = 0x0004800d,
};

extern int /*rc*/ bcm_mailbox_read(unsigned chan, uint32_t *data28);
extern int /*rc*/ bcm_mailbox_write(unsigned chan, uint32_t data28);
extern int /*rc*/ bcm_mailbox_property(void *data, int size);

#endif
47 changes: 18 additions & 29 deletions arch/arm/mach-bcm2708/vc_mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,44 +128,33 @@ struct vc_set_msg {
uint32_t end_tag; /* an end identifier, should be set to NULL */
};

#define VCMSG_GET_ARM_MEMORY 0x00010005
#define VCMSG_GET_VC_MEMORY 0x00010006

static void vc_mem_update(void)
{
uint32_t success;
dma_addr_t vc_mem; /* the memory address accessed from videocore */
struct vc_set_msg *get_mem; /* the memory address accessed from driver */

/* allocate some memory for the messages to use throughout the lifetime of the driver, use the larger of the two message structures */
get_mem = (struct vc_set_msg *)dma_alloc_coherent(NULL, PAGE_ALIGN(sizeof(struct vc_set_msg)), &vc_mem, GFP_ATOMIC);
/* clear any garbage */
memset(get_mem, 0, sizeof(struct vc_set_msg));
struct vc_set_msg msg; /* the memory address accessed from driver */
uint32_t s;

memset(&msg, 0, sizeof msg);
/* create the message */
get_mem->msg_size = sizeof(struct vc_set_msg);
get_mem->tag[0].tag_id = VCMSG_GET_VC_MEMORY;
get_mem->tag[0].buffer_size = 8;
get_mem->tag[0].data_size = 0;
get_mem->tag[1].tag_id = VCMSG_GET_ARM_MEMORY;
get_mem->tag[1].buffer_size = 8;
get_mem->tag[1].data_size = 0;
msg.msg_size = sizeof msg;
msg.tag[0].tag_id = VCMSG_GET_VC_MEMORY;
msg.tag[0].buffer_size = 8;
msg.tag[0].data_size = 0;
msg.tag[1].tag_id = VCMSG_GET_ARM_MEMORY;
msg.tag[1].buffer_size = 8;
msg.tag[1].data_size = 0;

/* send the message */
wmb();
bcm_mailbox_write(MBOX_CHAN_PROPERTY,(uint32_t)vc_mem);
bcm_mailbox_read(MBOX_CHAN_PROPERTY, &success);
rmb();
s = bcm_mailbox_property(&msg, sizeof msg);

LOG_DBG("%s: resp %x, vcbase=%x vcsize=%x armbase=%x armsize=%x", __func__, get_mem->request_code,
get_mem->tag[0].base, get_mem->tag[0].size, get_mem->tag[1].base, get_mem->tag[1].size);
LOG_DBG("%s: success=%d resp %x, vcbase=%x vcsize=%x armbase=%x armsize=%x", __func__, s, msg.request_code,
msg.tag[0].base, msg.tag[0].size, msg.tag[1].base, msg.tag[1].size);

/* check we're all good */
if (get_mem->request_code & 0x80000000) {
mm_vc_mem_base = get_mem->tag[0].base;
mm_vc_mem_size = get_mem->tag[0].size+get_mem->tag[1].size;
mm_vc_mem_phys_addr = get_mem->tag[1].base;
if (s == 0 && msg.request_code & 0x80000000) {
mm_vc_mem_base = msg.tag[0].base;
mm_vc_mem_size = msg.tag[0].size+msg.tag[1].size;
mm_vc_mem_phys_addr = msg.tag[1].base;
}
dma_free_coherent(NULL, PAGE_ALIGN(sizeof(struct vc_set_msg)), (void *)get_mem, vc_mem);
}


Expand Down
34 changes: 34 additions & 0 deletions arch/arm/mach-bcm2708/vcio.c
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,40 @@ static void dev_mbox_register(const char *dev_name, struct device *dev)
mbox_dev = dev;
}

extern int bcm_mailbox_property(void *data, int size)
{

This comment has been minimized.

Copy link
@huceke

huceke Sep 10, 2012

Is there a special reason why this function is declared extern in the .c file ?

This comment has been minimized.

Copy link
@popcornmix

popcornmix Sep 10, 2012

Author Collaborator

No reason. It is harmless from a C point of view, but I agree it's not necessary, and so should not be there.

uint32_t success;
dma_addr_t mem_bus; /* the memory address accessed from videocore */
void *mem_kern; /* the memory address accessed from driver */
int s = 0;

/* allocate some memory for the messages communicating with GPU */
mem_kern = dma_alloc_coherent(NULL, PAGE_ALIGN(size), &mem_bus, GFP_ATOMIC);
if (mem_kern) {
/* create the message */
memcpy(mem_kern, data, size);

/* send the message */
wmb();
s = bcm_mailbox_write(MBOX_CHAN_PROPERTY, (uint32_t)mem_bus);
if (s == 0) {
s = bcm_mailbox_read(MBOX_CHAN_PROPERTY, &success);
}
if (s == 0) {
/* copy the response */
rmb();
memcpy(data, mem_kern, size);
}
dma_free_coherent(NULL, PAGE_ALIGN(size), mem_kern, mem_bus);
} else {
s = -ENOMEM;
}
if (s != 0)
printk(KERN_ERR DRIVER_NAME ": %s failed (%d)\n", __func__, s);
return s;
}
EXPORT_SYMBOL_GPL(bcm_mailbox_property);

/* ----------------------------------------------------------------------
* Platform Device for Mailbox
* -------------------------------------------------------------------- */
Expand Down
8 changes: 8 additions & 0 deletions drivers/cpufreq/Kconfig.arm
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,11 @@ config ARM_EXYNOS4210_CPUFREQ
SoC (S5PV310 or S5PC210).

If in doubt, say N.

config ARM_BCM2835_CPUFREQ
bool "BCM2835 Driver"
default y
help
This adds the CPUFreq driver for BCM2835

If in doubt, say N.
1 change: 1 addition & 0 deletions drivers/cpufreq/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ obj-$(CONFIG_UX500_SOC_DB8500) += db8500-cpufreq.o
obj-$(CONFIG_ARM_S3C64XX_CPUFREQ) += s3c64xx-cpufreq.o
obj-$(CONFIG_ARM_S5PV210_CPUFREQ) += s5pv210-cpufreq.o
obj-$(CONFIG_ARM_EXYNOS4210_CPUFREQ) += exynos4210-cpufreq.o
obj-$(CONFIG_ARM_BCM2835_CPUFREQ) += bcm2835-cpufreq.o

##################################################################################
# PowerPC platform drivers
Expand Down
Loading

10 comments on commit adae199

@huceke
Copy link

@huceke huceke commented on adae199 Sep 10, 2012

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't compile : http://pastebin.com/9eTyXs8E

@popcornmix
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will with KALLSYMS_EXTRA_PASS=1. It's not this change that makes that necessary (I added it months ago).
Not sure what the real cause is.

@huceke
Copy link

@huceke huceke commented on adae199 Sep 10, 2012

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why should i add KALLSYMS_EXTRA_PASS to make. Never seen that this option is required for a kernel build. The PI one is the first one where this is necessary.

@popcornmix
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the output of:
diff .tmp_kallsyms2.S .tmp_kallsyms3.S
may give a hint as to what's causing this failure.
(I think you need to do KALLSYMS_EXTRA_PASS=1 first, then run the diff).

For me it's currently building with or without KALLSYMS_EXTRA_PASS=1, so I can't identify the problem.

@huceke
Copy link

@huceke huceke commented on adae199 Sep 10, 2012

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

http://pastebin.com/aCAgUd6m

A small part of the diff.

@popcornmix
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was hoping for symbol names. What about
diff .tmp_System.map System.map

https://lkml.org/lkml/2011/8/2/233

@huceke
Copy link

@huceke huceke commented on adae199 Sep 10, 2012

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When i go back to commit 55549f3 KALLSYMS_EXTRA_PASS is not needed. Diff of the System.map will follow.

@popcornmix
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From:
http://paste.ubuntu.com/1196699/
Looks like kallsyms_names is 16 bytes bigger in one than the other.
The references I've found suggests a bug in kallsyms.c. Need to ask asb...

@asb
Copy link

@asb asb commented on adae199 Sep 10, 2012

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Almost all evidence points to this being an upstream bug, rather than something we have introduced to the Linux build system.

There's some discussion here djwillis/meta-raspberrypi#38 and LKML discussion/patch here https://lkml.org/lkml/2012/6/1/267 and some more in-depth discussion here: http://www.spinics.net/lists/linux-kbuild/msg06042.html

I was going to suggest we wait until this is fixed upstream, but I'm pleased to see that a derivative of David Brown's proposed patch has been applied: http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=9973290ce20ace7cac8ad06f753468c0b826fd0f

We can apply that patch to our tree trivially (only reason we can't just git apply without manual fixup is that "PERCPU_SECTION(32)" has since been changed to "PERCPU_SECTION(L1_CACHE_BYTES)".

It looks like it shouldn't hurt for us to pull in this patch, but if @huceke you could double check that applying it fixes the build on your configuration that would be great.

@popcornmix
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Alex. Good investigative work. I seem to be building successfully without KALLSYMS_EXTRA_PASS, so I've committed the patch.

Please sign in to comment.